From 58e64e752ca4725c46b51ed451ce79f044a1f9a4 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 7 Jan 2018 10:33:38 +0100 Subject: [PATCH] python: upgrade notebook format to v4 Fixes #311. * tests/python/ipnbdoctest.py: Adjust to process the new format, with a lot of inspiration from Vcsn's copy of this file. * tests/python/_altscc.ipynb, tests/python/_aux.ipynb, tests/python/acc_cond.ipynb, tests/python/accparse.ipynb, tests/python/alternation.ipynb, tests/python/atva16-fig2a.ipynb, tests/python/atva16-fig2b.ipynb, tests/python/automata-io.ipynb, tests/python/automata.ipynb, tests/python/decompose.ipynb, tests/python/formulas.ipynb, tests/python/gen.ipynb, tests/python/highlighting.ipynb, tests/python/ltsmin-dve.ipynb, tests/python/ltsmin-pml.ipynb, tests/python/parity.ipynb, tests/python/piperead.ipynb, tests/python/product.ipynb, tests/python/randaut.ipynb, tests/python/randltl.ipynb, tests/python/stutter-inv.ipynb, tests/python/testingaut.ipynb, tests/python/word.ipynb: Upgrade to the new format. * NEWS: Mention the change. --- NEWS | 2 + tests/python/_altscc.ipynb | 2033 +++--- tests/python/_aux.ipynb | 127 +- tests/python/acc_cond.ipynb | 2940 ++++---- tests/python/accparse.ipynb | 312 +- tests/python/alternation.ipynb | 3596 +++++----- tests/python/atva16-fig2a.ipynb | 452 +- tests/python/atva16-fig2b.ipynb | 642 +- tests/python/automata-io.ipynb | 1675 +++-- tests/python/automata.ipynb | 7214 ++++++++++---------- tests/python/decompose.ipynb | 10848 +++++++++++++++--------------- tests/python/formulas.ipynb | 1738 ++--- tests/python/gen.ipynb | 1833 ++--- tests/python/highlighting.ipynb | 4984 +++++++------- tests/python/ipnbdoctest.py | 214 +- tests/python/ltsmin-dve.ipynb | 3044 ++++----- tests/python/ltsmin-pml.ipynb | 1299 ++-- tests/python/parity.ipynb | 3887 +++++------ tests/python/piperead.ipynb | 975 ++- tests/python/product.ipynb | 4592 ++++++------- tests/python/randaut.ipynb | 4541 +++++++------ tests/python/randltl.ipynb | 1299 ++-- tests/python/stutter-inv.ipynb | 5604 +++++++-------- tests/python/testingaut.ipynb | 1280 ++-- tests/python/word.ipynb | 1404 ++-- 25 files changed, 33431 insertions(+), 33104 deletions(-) diff --git a/NEWS b/NEWS index 9b9cfd9f8..8e570c30f 100644 --- a/NEWS +++ b/NEWS @@ -234,6 +234,8 @@ New in spot 2.4.4.dev (net yet released) signal per atomic proposition. For some examples, see the use of the show() method in https://spot.lrde.epita.fr/ipynb/word.html + - The test suite is now using v4 of the Jupyter Notebook format. + Deprecation notices: (These functions still work but compilers emit warnings.) diff --git a/tests/python/_altscc.ipynb b/tests/python/_altscc.ipynb index 6c67c1445..92a62c6b0 100644 --- a/tests/python/_altscc.ipynb +++ b/tests/python/_altscc.ipynb @@ -1,4 +1,1023 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These examples are tests for scc_info on alternating automata." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "import spot\n", + "spot.setup(show_default='.bas')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "I->-1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e84e9810> >" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('''\n", + "HOA: v1\n", + "States: 2\n", + "Start: 0&1\n", + "AP: 2 \"a\" \"b\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0\n", + "[!0] 1\n", + "State: 1\n", + "[1] 1 {0}\n", + "--END--\n", + "''')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "universal edges are handled as if they were many distinct existencial edges from the point of view of `scc_info`, so the acceptance / rejection status is not always meaningful." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "I->-1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e8571900> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('''\n", + "HOA: v1\n", + "States: 2\n", + "Start: 0&1\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0&1 {0}\n", + "State: 1\n", + "[1] 1\n", + "--END--\n", + "''')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "I->-1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e85070f0> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('''\n", + "HOA: v1\n", + "States: 2\n", + "Start: 0&1\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0 {0}\n", + "[!0] 1\n", + "State: 1\n", + "[1] 1&0\n", + "--END--\n", + "''')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e8507120> >" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('''\n", + "HOA: v1\n", + "States: 2\n", + "Start: 0\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0\n", + "[!0] 1 {0}\n", + "State: 1\n", + "[1] 1&0\n", + "--END--\n", + "''')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e8507150> >" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('''\n", + "HOA: v1\n", + "States: 2\n", + "Start: 0\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0 {0}\n", + "[!0] 1 \n", + "State: 1\n", + "[1] 1&0 {0}\n", + "--END--\n", + "''')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A corner case for the dot printer" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "-1->2\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e8507630> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "-1->2\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e84e98a0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "-4\n", + "\n", + "\n", + "\n", + "I->-4\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "-4->2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "-4->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "-1->2\n", + "\n", + "\n", + "\n", + "\n", + "2->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f41e9624660> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "-4\n", + "\n", + "\n", + "\n", + "I->-4\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "-4->2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "-4->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1.2\n", + "\n", + "\n", + "\n", + "1->-1.2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "-1.2->1\n", + "\n", + "\n", + "\n", + "\n", + "-1.2->2\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "2->-1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "-1->2\n", + "\n", + "\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for a in spot.automata('''\n", + "HOA: v1\n", + "States: 3\n", + "Start: 0\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 1&2\n", + "State: 1\n", + "[1] 1&2 {0}\n", + "State: 2\n", + "[1] 2\n", + "--END--\n", + "HOA: v1\n", + "States: 3\n", + "Start: 0\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 1&2\n", + "State: 1\n", + "[1] 1 {0}\n", + "State: 2\n", + "[1] 2\n", + "--END--\n", + "'''):\n", + " display(a)\n", + "\n", + "a = spot.automaton('''\n", + "HOA: v1\n", + "States: 3\n", + "Start: 0&2\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Fin(0)\n", + "spot.highlight.edges: 2 2\n", + "--BODY--\n", + "State: 0\n", + "[0] 1&2\n", + "State: 1\n", + "[1] 1&2 {0}\n", + "State: 2\n", + "[1] 1&2\n", + "--END--\n", + "''')\n", + "display(a, a.show('.basy'))" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,1016 +1035,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These examples are tests for scc_info on alternating automata." - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "from IPython.display import display\n", - "import spot\n", - "spot.setup(show_default='.bas')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('''\n", - "HOA: v1\n", - "States: 2\n", - "Start: 0&1\n", - "AP: 2 \"a\" \"b\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0\n", - "[!0] 1\n", - "State: 1\n", - "[1] 1 {0}\n", - "--END--\n", - "''')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "I->-1\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e84e9810> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "universal edges are handled as if they were many distinct existencial edges from the point of view of `scc_info`, so the acceptance / rejection status is not always meaningful." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('''\n", - "HOA: v1\n", - "States: 2\n", - "Start: 0&1\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0&1 {0}\n", - "State: 1\n", - "[1] 1\n", - "--END--\n", - "''')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "I->-1\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e8571900> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('''\n", - "HOA: v1\n", - "States: 2\n", - "Start: 0&1\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0 {0}\n", - "[!0] 1\n", - "State: 1\n", - "[1] 1&0\n", - "--END--\n", - "''')" - ], - "language": "python", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "I->-1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e85070f0> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('''\n", - "HOA: v1\n", - "States: 2\n", - "Start: 0\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0\n", - "[!0] 1 {0}\n", - "State: 1\n", - "[1] 1&0\n", - "--END--\n", - "''')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e8507120> >" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('''\n", - "HOA: v1\n", - "States: 2\n", - "Start: 0\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0 {0}\n", - "[!0] 1 \n", - "State: 1\n", - "[1] 1&0 {0}\n", - "--END--\n", - "''')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e8507150> >" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A corner case for the dot printer" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata('''\n", - "HOA: v1\n", - "States: 3\n", - "Start: 0\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 1&2\n", - "State: 1\n", - "[1] 1&2 {0}\n", - "State: 2\n", - "[1] 2\n", - "--END--\n", - "HOA: v1\n", - "States: 3\n", - "Start: 0\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 1&2\n", - "State: 1\n", - "[1] 1 {0}\n", - "State: 2\n", - "[1] 2\n", - "--END--\n", - "'''):\n", - " display(a)\n", - "\n", - "a = spot.automaton('''\n", - "HOA: v1\n", - "States: 3\n", - "Start: 0&2\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Fin(0)\n", - "spot.highlight.edges: 2 2\n", - "--BODY--\n", - "State: 0\n", - "[0] 1&2\n", - "State: 1\n", - "[1] 1&2 {0}\n", - "State: 2\n", - "[1] 1&2\n", - "--END--\n", - "''')\n", - "display(a, a.show('.basy'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "-1->2\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e8507630> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "-1->2\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e84e98a0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "-4\n", - "\n", - "\n", - "\n", - "I->-4\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "-4->2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "-4->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "-1->2\n", - "\n", - "\n", - "\n", - "\n", - "2->-1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f41e9624660> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "-4\n", - "\n", - "\n", - "\n", - "I->-4\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "-4->2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "-4->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1.2\n", - "\n", - "\n", - "\n", - "1->-1.2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "-1.2->1\n", - "\n", - "\n", - "\n", - "\n", - "-1.2->2\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "2->-1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "-1->2\n", - "\n", - "\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 7 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/_aux.ipynb b/tests/python/_aux.ipynb index ed3527d71..c90d7995c 100644 --- a/tests/python/_aux.ipynb +++ b/tests/python/_aux.ipynb @@ -1,73 +1,72 @@ { - "metadata": { - "name": "", - "signature": "sha256:6be10f711b59f226415bc570a040611b0a8c554e61bf92877b8af4040963e0ac" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import spot.aux" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make sure `str_to_svg` reports errors from dot." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot.aux" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make sure `str_to_svg` reports errors from dot." + "name": "stderr", + "output_type": "stream", + "text": [ + "Calling 'dot' for the conversion to SVG produced the message:\n", + "Error: : syntax error in line 1 near 'syntax'\n", + "\n" ] }, { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.aux.str_to_svg(b'syntax error')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stderr", - "text": [ - "Calling 'dot' for the conversion to SVG produced the message:\n", - "Error: : syntax error in line 1 near 'syntax'\n", - "\n" - ] - }, - { - "ename": "CalledProcessError", - "evalue": "Command 'dot' returned non-zero exit status 1", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maux\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstr_to_svg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mb'syntax error'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/aux.py\u001b[0m in \u001b[0;36mstr_to_svg\u001b[0;34m(str)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0mret\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 61\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 62\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'dot'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 63\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mstdout\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'utf-8'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mCalledProcessError\u001b[0m: Command 'dot' returned non-zero exit status 1" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [] + "ename": "CalledProcessError", + "evalue": "Command 'dot' returned non-zero exit status 1.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maux\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstr_to_svg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mb'syntax error'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/aux.py\u001b[0m in \u001b[0;36mstr_to_svg\u001b[0;34m(str)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[0mret\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 64\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'dot'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 65\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mstdout\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'utf-8'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mCalledProcessError\u001b[0m: Command 'dot' returned non-zero exit status 1." + ] } ], - "metadata": {} + "source": [ + "spot.aux.str_to_svg(b'syntax error')" + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/python/acc_cond.ipynb b/tests/python/acc_cond.ipynb index bcff265be..070318900 100644 --- a/tests/python/acc_cond.ipynb +++ b/tests/python/acc_cond.ipynb @@ -1,4 +1,1497 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Acceptance conditions\n", + "\n", + "The acceptance condition of an automaton specifies which of its paths are accepting.\n", + "\n", + "The way acceptance conditions are stored in Spot is derived from the way acceptance conditions are specified in the [HOA format](http://adl.github.io/hoaf/). In HOA, acceptance conditions are given as a line of the form:\n", + "\n", + " Acceptance: 3 (Inf(0)&Fin(1))|Inf(2)\n", + "\n", + "The number `3` gives the number of acceptance sets used (numbered from `0` to `2` in that case), while the rest of the line is a positive Boolean formula over terms of the form:\n", + "- `Inf(n)`, that is true if and only if the set `n` is seen infinitely often,\n", + "- `Fin(n)`, that is true if and only if the set `n` should be seen finitely often,\n", + "- `t`, always true,\n", + "- `f`, always false.\n", + "\n", + "The HOA specifications additionally allows terms of the form `Inf(!n)` or `Fin(!n)` but Spot automatically rewrites those away when reading an HOA file.\n", + "\n", + "Note that the number of sets given can be larger than what is actually needed by the acceptance formula.\n", + "\n", + "Transitions in automata can be tagged as being part of some member sets, and a path in the automaton is accepting if the set of acceptance sets visited along this path satify the acceptance condition.\n", + "\n", + "Definining acceptance conditions in Spot involves three different types of C++ objects:\n", + "\n", + "- `spot::acc_cond` is used to represent an acceptance condition, that is: a number of sets and a formula.\n", + "- `spot::acc_cond::acc_code`, is used to represent Boolean formula for the acceptance condition using a kind of byte code (hence the name)\n", + "- `spot::acc_cond::mark_t`, is a type of bit-vector used to represent membership to acceptance sets.\n", + "\n", + "In because Swig's support for nested class is limited, these types are available respectively as `spot.acc_cond`, `spot.acc_code`, and `spot.mark_t` in Python.\n", + "\n", + "## `mark_t`\n", + "\n", + "Let's start with the simpler of these three objects. `mark_t` is a type of bit vector. Its main constructor takes a sequence of set numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mark_t()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{0,2,3}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mark_t([0, 2, 3])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{0,2,3}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mark_t((0, 2, 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As seen above, the sequence of set numbers can be specified using a list or a tuple. While from the Python language point of view, using a tuple is faster than using a list, the overhead to converting all the arguments from Python to C++ and then converting the resuslting back from C++ to Python makes this difference completely negligeable. In the following, we opted to use lists, because brackets are more readable than nested parentheses." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2,3,4}\n", + "{0}\n", + "{2,3}\n" + ] + } + ], + "source": [ + "x = spot.mark_t([0, 2, 3])\n", + "y = spot.mark_t([0, 4])\n", + "print(x | y)\n", + "print(x & y)\n", + "print(x - y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The bits can be set, cleared, and tested using the `set()`, `clear()`, and `has()` methods:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2,3,5}\n" + ] + } + ], + "source": [ + "x.set(5)\n", + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2,5}\n" + ] + } + ], + "source": [ + "x.clear(3)\n", + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n" + ] + } + ], + "source": [ + "print(x.has(2))\n", + "print(x.has(3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Left-shifting will increment all set numbers.\n", + "This operation is useful when building the product of two automata: all the set number of one automaton have to be shift by the number of sets used in the other automaton." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2,4,7}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x << 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Internally, the `mark_t` stores the bit-vector as an integer. This also implies that we currently do not support more than 32 acceptance sets. The underlaying integer can be retrieved using `.id`." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2,5}\n", + "37\n", + "0b100101\n" + ] + } + ], + "source": [ + "print(x)\n", + "print(x.id)\n", + "print(bin(x.id))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`mark_t` can also be initialized using an integer: in that case the integer is interpreted as a bit vector.\n", + "\n", + "A frequent error is to use `mark_t(n)` when we really mean `mark_t([n])` or `mark_t((n,))`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{5}\n", + "{0,2}\n", + "{0,2,4}\n" + ] + } + ], + "source": [ + "# compare\n", + "print(spot.mark_t([5]))\n", + "# with\n", + "print(spot.mark_t(5))\n", + "print(spot.mark_t(0b10101))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The different sets can be iterated over with the `sets()` method, that returns a tuble with the index of all bits set." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2,5}\n", + "[0, 2, 5]\n", + "0\n", + "2\n", + "5\n" + ] + } + ], + "source": [ + "print(x)\n", + "print(list(x.sets()))\n", + "for s in x.sets():\n", + " print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`count()` return the number of sets in a `mark_t`:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x.count()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`lowest()` returns a `mark_t` containing only the lowest set number. This provides another way to iterate overs all set numbers in cases where you need the result as a `mark_t`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mark_t([1,3,5]).lowest()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{1}\n", + "{3}\n", + "{5}\n" + ] + } + ], + "source": [ + "v = spot.mark_t([1, 3, 5])\n", + "while v: # this stops once v is empty\n", + " b = v.lowest()\n", + " v -= b\n", + " print(b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`max_set()` returns the number of the highest set plus one. This is usually used to figure out how many sets we need to declare on the `Acceptance:` line of the HOA format:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mark_t([1, 3, 5]).max_set()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `acc_code`\n", + "\n", + "`acc_code` encodes the formula of the acceptance condition using a kind of bytecode that basically corresponds to an encoding in [reverse Polish notation](http://en.wikipedia.org/wiki/Reverse_Polish_notation) in which conjunctions of `Inf(n)` terms, and disjunctions of `Fin(n)` terms are grouped. In particular, the frequently-used genaralized-Büchi acceptance conditions (like `Inf(0)&Inf(1)&Inf(2)`) are always encoded as a single term (like `Inf({0,1,2})`).\n", + "\n", + "The simplest way to construct an `acc_code` by passing a string that represent the formula to build." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Inf(0) & Fin(1)) | Inf(2)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code('(Inf(0)&Fin(1))|Inf(2)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may also use a named acceptance condition:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code('Rabin 2')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The recognized names are the valide values for `acc-name:` in the [HOA format](http://adl.github.io/hoaf/). Additionally numbers may be replaced by ranges of the form `n..m`, in which case a random number is selected in that range." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Fin(0) | Inf(1)) & (Fin(2) | Inf(3)) & (Fin(4) | Inf(5)) & (Fin(6) | Inf(7))\n", + "(Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n" + ] + } + ], + "source": [ + "print(spot.acc_code('Streett 2..4'))\n", + "print(spot.acc_code('Streett 2..4'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It may also be convenient to generate a random acceptance condition:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(3) | Inf(1)) & Inf(4) & (Fin(0)|Fin(2))" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code('random 3..5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `to_cnf()` and `to_dnf()` functions can be used to rewrite the formula into Conjunctive or Disjunctive normal forms. This functions will simplify the resulting formulas to make them irredundant." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | Fin(4))))" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.acc_code('parity min odd 5')\n", + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Fin(0) & (Inf(1) | Fin(2)) & (Inf(1) | Inf(3) | Fin(4))" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.to_cnf()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(0) & Inf(1)) | (Fin(0) & Fin(2) & Inf(3)) | (Fin(0) & Fin(2) & Fin(4))" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.to_dnf()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The manipulation of `acc_code` objects is quite rudimentary at the moment: it easy to build, but it's harder take appart. In fact we won't attempt to disassemble an `acc_code` object in Python: those things are better done in C++\n", + "\n", + "Operators `|`, `|=`, `&`, `&=`, `<<`, and `<<=` can be used with their obvious semantics.\n", + "Whenever possible, the inplace versions (`|=`, `&=`, `<<=`) should be prefered, because they create less temporary acceptance conditions." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", + "(Fin(4) & Inf(5)) | (Fin(6) & Inf(7))\n" + ] + } + ], + "source": [ + "x = spot.acc_code('Rabin 2')\n", + "y = spot.acc_code('Rabin 2') << 4\n", + "print(x)\n", + "print(y)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Fin(4) & Inf(5)) | (Fin(6) & Inf(7)) | (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", + "((Fin(4) & Inf(5)) | (Fin(6) & Inf(7))) & ((Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))\n" + ] + } + ], + "source": [ + "print(x | y)\n", + "print(x & y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `complement()` method returns the complemented acceptance condition:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", + "(Inf(0) | Fin(1)) & (Inf(2) | Fin(3))\n" + ] + } + ], + "source": [ + "print(x)\n", + "print(x.complement())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead of using `acc_code('string')`, it is also possible to build an acceptance formula from atoms like `Inf({...})`, `Fin({...})`, `t`, or `f`.\n", + "\n", + "Remember that in our encoding for the formula, terms like `Inf(1)&Inf(2)` and `Fin(3)|Fin(4)|Fin(5)` are actually stored as `Inf({1,2})` and `Fin({3,4,5})`, where `{1,2}` and `{3,4,5}` are instance of `mark_t`. These terms can be generated with the\n", + "functions `spot.acc_code.inf(mark)` and `spot.acc_code.fin(mark)`.\n", + "\n", + "`Inf({})` is equivalent to `t`, and `Fin({})` is equivalent to `f`, but it's better to use the functions `spot.acc_code.t()` or `spot.acc_code.f()` directly." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(3)|Fin(4)|Fin(5)) & (Inf(1)&Inf(2))" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code.inf([1,2]) & spot.acc_code.fin([3,4,5])" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "t" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code.inf([])" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "t" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code.t()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "f" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code.fin([])" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "f" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.acc_code.f()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To evaluate an acceptance condition formula on a run, build a `mark_t` containing all the acceptance sets that are seen infinitely often along this run, and call the `accepting()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "acc = (Fin(0) & Inf(1)) | Inf(2)\n", + "acc.accepting([0, 1, 2]) = True\n", + "acc.accepting([1, 2]) = True\n", + "acc.accepting([0, 1]) = False\n", + "acc.accepting([0, 2]) = True\n", + "acc.accepting([0]) = False\n", + "acc.accepting([1]) = True\n", + "acc.accepting([2]) = True\n", + "acc.accepting([]) = False\n" + ] + } + ], + "source": [ + "acc = spot.acc_code('Fin(0) & Inf(1) | Inf(2)')\n", + "print(\"acc =\", acc)\n", + "for x in ([0, 1, 2], [1, 2], [0, 1], [0, 2], [0], [1], [2], []):\n", + " print(\"acc.accepting({}) = {}\".format(x, acc.accepting(x)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally the method `used_sets()` returns a `mark_t` with all the sets appearing in the formula:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fin(0) & Inf(2)\n", + "{0,2}\n", + "3\n" + ] + } + ], + "source": [ + "acc = spot.acc_code('Fin(0) & Inf(2)')\n", + "print(acc)\n", + "print(acc.used_sets())\n", + "print(acc.used_sets().max_set())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# `acc_cond`\n", + "\n", + "Automata store their acceptance condition as an instance of the `acc_cond` class.\n", + "This class can be thought of as a pair `(n, code)`, where `n` is an integer that tells how many acceptance sets are used, while the `code` is an instance of `acc_code` and encodes the formula over *a subset* of these acceptance sets. We usually have `n == code.used_sets().max_set())`, but `n` can be larger.\n", + "\n", + "It is OK if an automaton declares that is used 3 sets, even if the acceptance condition formula only uses set number 1.\n", + "\n", + "The `acc_cond` objects are usually not created by hand: automata have dedicated methods for that. But for the purpose of this notebook, let's do it:" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc = spot.acc_cond(4, spot.acc_code('Rabin 2'))\n", + "acc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For convenience, you can pass the string directly:" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc = spot.acc_cond(4, 'Rabin 2')\n", + "acc" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc.num_sets()" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc.get_acceptance()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `acc_cond` object can also be constructed using only a number of sets. In that case, the acceptance condition defaults to `t`, and it can be changed to something else later (using `set_acceptance()`). The number of acceptance sets can also be augmented with `add_sets()`." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, t)" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc = spot.acc_cond(4)\n", + "acc" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(6, t)" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc.add_sets(2)\n", + "acc" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(6, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc.set_acceptance('Streett 2')\n", + "acc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calling the constructor of `acc_cond` by passing just an instance of `acc_code` (or a string that will be passed to the `acc_code` constructor) will automatically set the number of acceptance sets to the minimum needed by the formula:" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc = spot.acc_cond('Streett 2')\n", + "acc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above is in fact just syntactic sugar for:" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "code = spot.acc_code('Streett 2')\n", + "acc = spot.acc_cond(code.used_sets().max_set(), code)\n", + "acc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The common scenario of setting generalized Büchi acceptance can be achieved more efficiently by first setting the number of acceptance sets, and then requiring generalized Büchi acceptance:" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc = spot.acc_cond(4)\n", + "acc.set_generalized_buchi()\n", + "acc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `acc_cond` class has several methods for detecting acceptance conditions that match the named acceptance conditions of the HOA format. Note that in the HOA format, `Inf(0)&Inf(1)&Inf(2)&Inf(3)` is only called generalized Büchi if exactly 4 acceptance sets are used. So the following behavior should not be surprising:" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", + "True\n", + "(5, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", + "False\n" + ] + } + ], + "source": [ + "print(acc)\n", + "print(acc.is_generalized_buchi())\n", + "acc.add_sets(1)\n", + "print(acc)\n", + "print(acc.is_generalized_buchi())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similar methods like `is_t()`, `is_f()`, `is_buchi()`, `is_co_buchi()`, `is_generalized_co_buchi()` all return a Boolean.\n", + "\n", + "The `is_rabin()` and `is_streett()` methods, however, return a number of pairs. The number of pairs is always `num_sets()/2` on success, or -1 on failure." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))\n", + "2\n", + "-1\n" + ] + } + ], + "source": [ + "acc = spot.acc_cond('Rabin 2')\n", + "print(acc)\n", + "print(acc.is_rabin())\n", + "print(acc.is_streett())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The check for parity acceptance returns three Boolean in a list of the form `[matched, max?, odd?]`. If `matched` is `False`, the other values should be ignored." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, Fin(0) & (Inf(1) | (Fin(2) & Inf(3))))\n", + "[True, False, True]\n", + "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", + "[False, False, False]\n" + ] + } + ], + "source": [ + "acc = spot.acc_cond('parity min odd 4')\n", + "print(acc)\n", + "print(acc.is_parity())\n", + "acc.set_generalized_buchi()\n", + "print(acc)\n", + "print(acc.is_parity())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the acceptance condition has some known name, it can be retrieved using the `name()` method. By default the name given is a human-readable string close that used in the HOA format, but with proper accents, and support for name like `Streett-like` or `Rabin-like`. The argument `arg` can specify a different style using the same syntax as in `--format='%[arg]g'` when using the command-line tools." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "generalized-Büchi 4\n", + "gen. Büchi 4\n", + "generalized-Buchi\n" + ] + } + ], + "source": [ + "print(acc.name())\n", + "print(acc.name(\"d\")) # <- Style used by print_dot(aut, \"a\")\n", + "print(acc.name(\"0\")) # <- no parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`acc_cond` contains a few functions for manipulating `mark_t` instances, these are typically functions that require known the total number of accepting sets declared.\n", + "\n", + "For instance complementing a `mark_t`:" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0,2}\n" + ] + } + ], + "source": [ + "m = spot.mark_t([1, 3])\n", + "print(acc.comp(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`all_sets()` returns a `mark_t` listing all the declared sets: " + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{0,1,2,3}" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acc.all_sets()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For convencience, the `accepting()` method of `acc_cond` delegates to that of the `acc_code`. \n", + "Any set passed to `accepting()` that is not used by the acceptance formula has no influence." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "acc = (4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", + "acc.accepting([0, 1, 2, 3, 10]) = True\n", + "acc.accepting([1, 2]) = False\n" + ] + } + ], + "source": [ + "print(\"acc =\", acc)\n", + "for x in ([0, 1, 2, 3, 10], [1, 2]):\n", + " print(\"acc.accepting({}) = {}\".format(x, acc.accepting(x)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally the `unsat_mark()` method of `acc_cond` computes an instance of `mark_t` that is unaccepting (i.e., passing this value to `acc.accepting(...)` will return `False` when such a value exist. Not all acceptance conditions have an satisfiable mark. Obviously the `t` acceptance is always satisfiable, and so are all equivalent acceptances (for instance `Fin(1)|Inf(1)`).\n", + "\n", + "For this reason, `unsat_mark()` actually returns a pair: `(bool, mark_t)` where the Boolean is `False` iff the acceptance is always satisfiable. When the Boolean is `True`, then the second element of the pair gives a non-accepting mark." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", + "(True, {})\n" + ] + } + ], + "source": [ + "print(acc)\n", + "print(acc.unsat_mark())" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, t)\n", + "(False, {})\n" + ] + } + ], + "source": [ + "acc = spot.acc_cond(0) # use 0 acceptance sets, and the default formula (t)\n", + "print(acc)\n", + "print(acc.unsat_mark())" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))\n", + "(True, {2})\n" + ] + } + ], + "source": [ + "acc = spot.acc_cond('Streett 2')\n", + "print(acc)\n", + "print(acc.unsat_mark())" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,1449 +1509,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Acceptance conditions\n", - "\n", - "The acceptance condition of an automaton specifies which of its paths are accepting.\n", - "\n", - "The way acceptance conditions are stored in Spot is derived from the way acceptance conditions are specified in the [HOA format](http://adl.github.io/hoaf/). In HOA, acceptance conditions are given as a line of the form:\n", - "\n", - " Acceptance: 3 (Inf(0)&Fin(1))|Inf(2)\n", - "\n", - "The number `3` gives the number of acceptance sets used (numbered from `0` to `2` in that case), while the rest of the line is a positive Boolean formula over terms of the form:\n", - "- `Inf(n)`, that is true if and only if the set `n` is seen infinitely often,\n", - "- `Fin(n)`, that is true if and only if the set `n` should be seen finitely often,\n", - "- `t`, always true,\n", - "- `f`, always false.\n", - "\n", - "The HOA specifications additionally allows terms of the form `Inf(!n)` or `Fin(!n)` but Spot automatically rewrites those away when reading an HOA file.\n", - "\n", - "Note that the number of sets given can be larger than what is actually needed by the acceptance formula.\n", - "\n", - "Transitions in automata can be tagged as being part of some member sets, and a path in the automaton is accepting if the set of acceptance sets visited along this path satify the acceptance condition.\n", - "\n", - "Definining acceptance conditions in Spot involves three different types of C++ objects:\n", - "\n", - "- `spot::acc_cond` is used to represent an acceptance condition, that is: a number of sets and a formula.\n", - "- `spot::acc_cond::acc_code`, is used to represent Boolean formula for the acceptance condition using a kind of byte code (hence the name)\n", - "- `spot::acc_cond::mark_t`, is a type of bit-vector used to represent membership to acceptance sets.\n", - "\n", - "In because Swig's support for nested class is limited, these types are available respectively as `spot.acc_cond`, `spot.acc_code`, and `spot.mark_t` in Python.\n", - "\n", - "## `mark_t`\n", - "\n", - "Let's start with the simpler of these three objects. `mark_t` is a type of bit vector. Its main constructor takes a sequence of set numbers." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mark_t()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "{}" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mark_t([0, 2, 3])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "{0,2,3}" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mark_t((0, 2, 3))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "text": [ - "{0,2,3}" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As seen above, the sequence of set numbers can be specified using a list or a tuple. While from the Python language point of view, using a tuple is faster than using a list, the overhead to converting all the arguments from Python to C++ and then converting the resuslting back from C++ to Python makes this difference completely negligeable. In the following, we opted to use lists, because brackets are more readable than nested parentheses." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x = spot.mark_t([0, 2, 3])\n", - "y = spot.mark_t([0, 4])\n", - "print(x | y)\n", - "print(x & y)\n", - "print(x - y)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2,3,4}\n", - "{0}\n", - "{2,3}\n" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The bits can be set, cleared, and tested using the `set()`, `clear()`, and `has()` methods:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x.set(5)\n", - "print(x)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2,3,5}\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x.clear(3)\n", - "print(x)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2,5}\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(x.has(2))\n", - "print(x.has(3))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "True\n", - "False\n" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Left-shifting will increment all set numbers.\n", - "This operation is useful when building the product of two automata: all the set number of one automaton have to be shift by the number of sets used in the other automaton." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x << 2" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "{2,4,7}" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Internally, the `mark_t` stores the bit-vector as an integer. This also implies that we currently do not support more than 32 acceptance sets. The underlaying integer can be retrieved using `.id`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(x)\n", - "print(x.id)\n", - "print(bin(x.id))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2,5}\n", - "37\n", - "0b100101\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`mark_t` can also be initialized using an integer: in that case the integer is interpreted as a bit vector.\n", - "\n", - "A frequent error is to use `mark_t(n)` when we really mean `mark_t([n])` or `mark_t((n,))`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# compare\n", - "print(spot.mark_t([5]))\n", - "# with\n", - "print(spot.mark_t(5))\n", - "print(spot.mark_t(0b10101))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{5}\n", - "{0,2}\n", - "{0,2,4}\n" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The different sets can be iterated over with the `sets()` method, that returns a tuble with the index of all bits set." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(x)\n", - "print(list(x.sets()))\n", - "for s in x.sets():\n", - " print(s)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2,5}\n", - "[0, 2, 5]\n", - "0\n", - "2\n", - "5\n" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`count()` return the number of sets in a `mark_t`:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x.count()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "text": [ - "3" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`lowest()` returns a `mark_t` containing only the lowest set number. This provides another way to iterate overs all set numbers in cases where you need the result as a `mark_t`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mark_t([1,3,5]).lowest()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "{1}" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "v = spot.mark_t([1, 3, 5])\n", - "while v: # this stops once v is empty\n", - " b = v.lowest()\n", - " v -= b\n", - " print(b)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{1}\n", - "{3}\n", - "{5}\n" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`max_set()` returns the number of the highest set plus one. This is usually used to figure out how many sets we need to declare on the `Acceptance:` line of the HOA format:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mark_t([1, 3, 5]).max_set()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "text": [ - "6" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `acc_code`\n", - "\n", - "`acc_code` encodes the formula of the acceptance condition using a kind of bytecode that basically corresponds to an encoding in [reverse Polish notation](http://en.wikipedia.org/wiki/Reverse_Polish_notation) in which conjunctions of `Inf(n)` terms, and disjunctions of `Fin(n)` terms are grouped. In particular, the frequently-used genaralized-B\u00fcchi acceptance conditions (like `Inf(0)&Inf(1)&Inf(2)`) are always encoded as a single term (like `Inf({0,1,2})`).\n", - "\n", - "The simplest way to construct an `acc_code` by passing a string that represent the formula to build." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code('(Inf(0)&Fin(1))|Inf(2)')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 17, - "text": [ - "(Inf(0) & Fin(1)) | Inf(2)" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You may also use a named acceptance condition:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code('Rabin 2')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "text": [ - "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The recognized names are the valide values for `acc-name:` in the [HOA format](http://adl.github.io/hoaf/). Additionally numbers may be replaced by ranges of the form `n..m`, in which case a random number is selected in that range." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.acc_code('Streett 2..4'))\n", - "print(spot.acc_code('Streett 2..4'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(Fin(0) | Inf(1)) & (Fin(2) | Inf(3)) & (Fin(4) | Inf(5)) & (Fin(6) | Inf(7))\n", - "(Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It may also be convenient to generate a random acceptance condition:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code('random 3..5')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 20, - "text": [ - "(Fin(3) | Inf(1)) & Inf(4) & (Fin(0)|Fin(2))" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `to_cnf()` and `to_dnf()` functions can be used to rewrite the formula into Conjunctive or Disjunctive normal forms. This functions will simplify the resulting formulas to make them irredundant." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.acc_code('parity min odd 5')\n", - "a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 21, - "text": [ - "Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | Fin(4))))" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.to_cnf()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 22, - "text": [ - "Fin(0) & (Inf(1) | Fin(2)) & (Inf(1) | Inf(3) | Fin(4))" - ] - } - ], - "prompt_number": 22 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.to_dnf()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 23, - "text": [ - "(Fin(0) & Inf(1)) | (Fin(0) & Fin(2) & Inf(3)) | (Fin(0) & Fin(2) & Fin(4))" - ] - } - ], - "prompt_number": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The manipulation of `acc_code` objects is quite rudimentary at the moment: it easy to build, but it's harder take appart. In fact we won't attempt to disassemble an `acc_code` object in Python: those things are better done in C++\n", - "\n", - "Operators `|`, `|=`, `&`, `&=`, `<<`, and `<<=` can be used with their obvious semantics.\n", - "Whenever possible, the inplace versions (`|=`, `&=`, `<<=`) should be prefered, because they create less temporary acceptance conditions." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "x = spot.acc_code('Rabin 2')\n", - "y = spot.acc_code('Rabin 2') << 4\n", - "print(x)\n", - "print(y)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", - "(Fin(4) & Inf(5)) | (Fin(6) & Inf(7))\n" - ] - } - ], - "prompt_number": 24 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(x | y)\n", - "print(x & y)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(Fin(4) & Inf(5)) | (Fin(6) & Inf(7)) | (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", - "((Fin(4) & Inf(5)) | (Fin(6) & Inf(7))) & ((Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))\n" - ] - } - ], - "prompt_number": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `complement()` method returns the complemented acceptance condition:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(x)\n", - "print(x.complement())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", - "(Inf(0) | Fin(1)) & (Inf(2) | Fin(3))\n" - ] - } - ], - "prompt_number": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instead of using `acc_code('string')`, it is also possible to build an acceptance formula from atoms like `Inf({...})`, `Fin({...})`, `t`, or `f`.\n", - "\n", - "Remember that in our encoding for the formula, terms like `Inf(1)&Inf(2)` and `Fin(3)|Fin(4)|Fin(5)` are actually stored as `Inf({1,2})` and `Fin({3,4,5})`, where `{1,2}` and `{3,4,5}` are instance of `mark_t`. These terms can be generated with the\n", - "functions `spot.acc_code.inf(mark)` and `spot.acc_code.fin(mark)`.\n", - "\n", - "`Inf({})` is equivalent to `t`, and `Fin({})` is equivalent to `f`, but it's better to use the functions `spot.acc_code.t()` or `spot.acc_code.f()` directly." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code.inf([1,2]) & spot.acc_code.fin([3,4,5])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 27, - "text": [ - "(Fin(3)|Fin(4)|Fin(5)) & (Inf(1)&Inf(2))" - ] - } - ], - "prompt_number": 27 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code.inf([])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 28, - "text": [ - "t" - ] - } - ], - "prompt_number": 28 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code.t()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 29, - "text": [ - "t" - ] - } - ], - "prompt_number": 29 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code.fin([])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 30, - "text": [ - "f" - ] - } - ], - "prompt_number": 30 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.acc_code.f()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 31, - "text": [ - "f" - ] - } - ], - "prompt_number": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To evaluate an acceptance condition formula on a run, build a `mark_t` containing all the acceptance sets that are seen infinitely often along this run, and call the `accepting()` method." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_code('Fin(0) & Inf(1) | Inf(2)')\n", - "print(\"acc =\", acc)\n", - "for x in ([0, 1, 2], [1, 2], [0, 1], [0, 2], [0], [1], [2], []):\n", - " print(\"acc.accepting({}) = {}\".format(x, acc.accepting(x)))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "acc = (Fin(0) & Inf(1)) | Inf(2)\n", - "acc.accepting([0, 1, 2]) = True\n", - "acc.accepting([1, 2]) = True\n", - "acc.accepting([0, 1]) = False\n", - "acc.accepting([0, 2]) = True\n", - "acc.accepting([0]) = False\n", - "acc.accepting([1]) = True\n", - "acc.accepting([2]) = True\n", - "acc.accepting([]) = False\n" - ] - } - ], - "prompt_number": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally the method `used_sets()` returns a `mark_t` with all the sets appearing in the formula:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_code('Fin(0) & Inf(2)')\n", - "print(acc)\n", - "print(acc.used_sets())\n", - "print(acc.used_sets().max_set())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Fin(0) & Inf(2)\n", - "{0,2}\n", - "3\n" - ] - } - ], - "prompt_number": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# `acc_cond`\n", - "\n", - "Automata store their acceptance condition as an instance of the `acc_cond` class.\n", - "This class can be thought of as a pair `(n, code)`, where `n` is an integer that tells how many acceptance sets are used, while the `code` is an instance of `acc_code` and encodes the formula over *a subset* of these acceptance sets. We usually have `n == code.used_sets().max_set())`, but `n` can be larger.\n", - "\n", - "It is OK if an automaton declares that is used 3 sets, even if the acceptance condition formula only uses set number 1.\n", - "\n", - "The `acc_cond` objects are usually not created by hand: automata have dedicated methods for that. But for the purpose of this notebook, let's do it:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond(4, spot.acc_code('Rabin 2'))\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 34, - "text": [ - "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))" - ] - } - ], - "prompt_number": 34 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For convenience, you can pass the string directly:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond(4, 'Rabin 2')\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 35, - "text": [ - "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))" - ] - } - ], - "prompt_number": 35 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc.num_sets()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 36, - "text": [ - "4" - ] - } - ], - "prompt_number": 36 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc.get_acceptance()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 37, - "text": [ - "(Fin(0) & Inf(1)) | (Fin(2) & Inf(3))" - ] - } - ], - "prompt_number": 37 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `acc_cond` object can also be constructed using only a number of sets. In that case, the acceptance condition defaults to `t`, and it can be changed to something else later (using `set_acceptance()`). The number of acceptance sets can also be augmented with `add_sets()`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond(4)\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 38, - "text": [ - "(4, t)" - ] - } - ], - "prompt_number": 38 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc.add_sets(2)\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 39, - "text": [ - "(6, t)" - ] - } - ], - "prompt_number": 39 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc.set_acceptance('Streett 2')\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 40, - "text": [ - "(6, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" - ] - } - ], - "prompt_number": 40 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calling the constructor of `acc_cond` by passing just an instance of `acc_code` (or a string that will be passed to the `acc_code` constructor) will automatically set the number of acceptance sets to the minimum needed by the formula:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond('Streett 2')\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 41, - "text": [ - "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" - ] - } - ], - "prompt_number": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above is in fact just syntactic sugar for:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "code = spot.acc_code('Streett 2')\n", - "acc = spot.acc_cond(code.used_sets().max_set(), code)\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 42, - "text": [ - "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))" - ] - } - ], - "prompt_number": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The common scenario of setting generalized B\u00fcchi acceptance can be achieved more efficiently by first setting the number of acceptance sets, and then requiring generalized B\u00fcchi acceptance:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond(4)\n", - "acc.set_generalized_buchi()\n", - "acc" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 43, - "text": [ - "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))" - ] - } - ], - "prompt_number": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `acc_cond` class has several methods for detecting acceptance conditions that match the named acceptance conditions of the HOA format. Note that in the HOA format, `Inf(0)&Inf(1)&Inf(2)&Inf(3)` is only called generalized B\u00fcchi if exactly 4 acceptance sets are used. So the following behavior should not be surprising:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(acc)\n", - "print(acc.is_generalized_buchi())\n", - "acc.add_sets(1)\n", - "print(acc)\n", - "print(acc.is_generalized_buchi())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", - "True\n", - "(5, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", - "False\n" - ] - } - ], - "prompt_number": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similar methods like `is_t()`, `is_f()`, `is_buchi()`, `is_co_buchi()`, `is_generalized_co_buchi()` all return a Boolean.\n", - "\n", - "The `is_rabin()` and `is_streett()` methods, however, return a number of pairs. The number of pairs is always `num_sets()/2` on success, or -1 on failure." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond('Rabin 2')\n", - "print(acc)\n", - "print(acc.is_rabin())\n", - "print(acc.is_streett())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(4, (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)))\n", - "2\n", - "-1\n" - ] - } - ], - "prompt_number": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The check for parity acceptance returns three Boolean in a list of the form `[matched, max?, odd?]`. If `matched` is `False`, the other values should be ignored." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond('parity min odd 4')\n", - "print(acc)\n", - "print(acc.is_parity())\n", - "acc.set_generalized_buchi()\n", - "print(acc)\n", - "print(acc.is_parity())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(4, Fin(0) & (Inf(1) | (Fin(2) & Inf(3))))\n", - "[True, False, True]\n", - "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", - "[False, False, False]\n" - ] - } - ], - "prompt_number": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the acceptance condition has some known name, it can be retrieved using the `name()` method. By default the name given is a human-readable string close that used in the HOA format, but with proper accents, and support for name like `Streett-like` or `Rabin-like`. The argument `arg` can specify a different style using the same syntax as in `--format='%[arg]g'` when using the command-line tools." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(acc.name())\n", - "print(acc.name(\"d\")) # <- Style used by print_dot(aut, \"a\")\n", - "print(acc.name(\"0\")) # <- no parameters" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "generalized-B\u00fcchi 4\n", - "gen. B\u00fcchi 4\n", - "generalized-Buchi\n" - ] - } - ], - "prompt_number": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`acc_cond` contains a few functions for manipulating `mark_t` instances, these are typically functions that require known the total number of accepting sets declared.\n", - "\n", - "For instance complementing a `mark_t`:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "m = spot.mark_t([1, 3])\n", - "print(acc.comp(m))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{0,2}\n" - ] - } - ], - "prompt_number": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`all_sets()` returns a `mark_t` listing all the declared sets: " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc.all_sets()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 49, - "text": [ - "{0,1,2,3}" - ] - } - ], - "prompt_number": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For convencience, the `accepting()` method of `acc_cond` delegates to that of the `acc_code`. \n", - "Any set passed to `accepting()` that is not used by the acceptance formula has no influence." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(\"acc =\", acc)\n", - "for x in ([0, 1, 2, 3, 10], [1, 2]):\n", - " print(\"acc.accepting({}) = {}\".format(x, acc.accepting(x)))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "acc = (4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", - "acc.accepting([0, 1, 2, 3, 10]) = True\n", - "acc.accepting([1, 2]) = False\n" - ] - } - ], - "prompt_number": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally the `unsat_mark()` method of `acc_cond` computes an instance of `mark_t` that is unaccepting (i.e., passing this value to `acc.accepting(...)` will return `False` when such a value exist. Not all acceptance conditions have an satisfiable mark. Obviously the `t` acceptance is always satisfiable, and so are all equivalent acceptances (for instance `Fin(1)|Inf(1)`).\n", - "\n", - "For this reason, `unsat_mark()` actually returns a pair: `(bool, mark_t)` where the Boolean is `False` iff the acceptance is always satisfiable. When the Boolean is `True`, then the second element of the pair gives a non-accepting mark." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(acc)\n", - "print(acc.unsat_mark())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(4, Inf(0)&Inf(1)&Inf(2)&Inf(3))\n", - "(True, {})\n" - ] - } - ], - "prompt_number": 51 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond(0) # use 0 acceptance sets, and the default formula (t)\n", - "print(acc)\n", - "print(acc.unsat_mark())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(0, t)\n", - "(False, {})\n" - ] - } - ], - "prompt_number": 52 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "acc = spot.acc_cond('Streett 2')\n", - "print(acc)\n", - "print(acc.unsat_mark())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(4, (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)))\n", - "(True, {2})\n" - ] - } - ], - "prompt_number": 53 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/accparse.ipynb b/tests/python/accparse.ipynb index 734e3e848..bb6518461 100644 --- a/tests/python/accparse.ipynb +++ b/tests/python/accparse.ipynb @@ -1,4 +1,157 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Inf(0) & Fin(1)) | (Inf(2) & Fin(3))" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = spot.acc_code('Inf(0)&Fin(1)|Inf(2)&Fin(3)'); c" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Fin(1) & Inf(0)) | (Fin(3) & Inf(2))" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.to_dnf()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(Inf(0) | Inf(2)) & (Inf(0) | Fin(3)) & (Inf(2) | Fin(1)) & (Fin(1)|Fin(3))" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.to_cnf()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "all: t\n", + "t: t\n", + "Buchi: Inf(0)\n", + "generalized-Buchi 3: Inf(0)&Inf(1)&Inf(2)\n", + "generalized-Buchi 0: t\n", + "co-Buchi: Fin(0)\n", + "generalized-co-Buchi 3: Fin(0)|Fin(1)|Fin(2)\n", + "generalized-co-Buchi 0: f\n", + "Rabin 2: (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", + "Rabin 0: f\n", + "Streett 2: (Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n", + "Streett 0: t\n", + "generalized-Rabin 3 1 2 3: (Fin(0) & Inf(1)) | (Fin(2) & (Inf(3)&Inf(4))) | (Fin(5) & (Inf(6)&Inf(7)&Inf(8)))\n", + "generalized-Rabin 0: f\n", + "parity min even 6: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & (Inf(4) | Fin(5)))))\n", + "parity max odd 6: Inf(5) | (Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))))\n", + "parity max even 6: Fin(5) & (Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))))\n", + "parity min odd 6: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | (Fin(4) & Inf(5)))))\n", + "parity min even 5: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & Inf(4))))\n", + "parity max odd 5: Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0))))\n", + "parity max even 5: Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0))))\n", + "parity min odd 5: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | Fin(4))))\n", + "parity min even 2: Inf(0) | Fin(1)\n", + "parity max odd 2: Inf(1) | Fin(0)\n", + "parity max even 2: Fin(1) & Inf(0)\n", + "parity min odd 2: Fin(0) & Inf(1)\n", + "parity min even 1: Inf(0)\n", + "parity max odd 1: Fin(0)\n", + "parity max even 1: Inf(0)\n", + "parity min odd 1: Fin(0)\n", + "parity min even 0: t\n", + "parity max odd 0: t\n", + "parity max even 0: f\n", + "parity min odd 0: f\n" + ] + } + ], + "source": [ + "for acc in ['all', 't', \n", + " 'Buchi', 'generalized-Buchi 3', 'generalized-Buchi 0',\n", + " 'co-Buchi', 'generalized-co-Buchi 3', 'generalized-co-Buchi 0',\n", + " 'Rabin 2', 'Rabin 0',\n", + " 'Streett 2', 'Streett 0',\n", + " 'generalized-Rabin 3 1 2 3', 'generalized-Rabin 0',\n", + " 'parity min even 6', 'parity max odd 6', 'parity max even 6', 'parity min odd 6',\n", + " 'parity min even 5', 'parity max odd 5', 'parity max even 5', 'parity min odd 5',\n", + " 'parity min even 2', 'parity max odd 2', 'parity max even 2', 'parity min odd 2',\n", + " 'parity min even 1', 'parity max odd 1', 'parity max even 1', 'parity min odd 1',\n", + " 'parity min even 0', 'parity max odd 0', 'parity max even 0', 'parity min odd 0',\n", + " ]:\n", + " print(acc, ': ', spot.acc_code(acc), sep='')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,161 +169,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3+" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": true, - "input": [ - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "c = spot.acc_code('Inf(0)&Fin(1)|Inf(2)&Fin(3)'); c" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "(Inf(0) & Fin(1)) | (Inf(2) & Fin(3))" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "c.to_dnf()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "(Fin(1) & Inf(0)) | (Fin(3) & Inf(2))" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "c.to_cnf()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "text": [ - "(Inf(0) | Inf(2)) & (Inf(0) | Fin(3)) & (Inf(2) | Fin(1)) & (Fin(1)|Fin(3))" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for acc in ['all', 't', \n", - " 'Buchi', 'generalized-Buchi 3', 'generalized-Buchi 0',\n", - " 'co-Buchi', 'generalized-co-Buchi 3', 'generalized-co-Buchi 0',\n", - " 'Rabin 2', 'Rabin 0',\n", - " 'Streett 2', 'Streett 0',\n", - " 'generalized-Rabin 3 1 2 3', 'generalized-Rabin 0',\n", - " 'parity min even 6', 'parity max odd 6', 'parity max even 6', 'parity min odd 6',\n", - " 'parity min even 5', 'parity max odd 5', 'parity max even 5', 'parity min odd 5',\n", - " 'parity min even 2', 'parity max odd 2', 'parity max even 2', 'parity min odd 2',\n", - " 'parity min even 1', 'parity max odd 1', 'parity max even 1', 'parity min odd 1',\n", - " 'parity min even 0', 'parity max odd 0', 'parity max even 0', 'parity min odd 0',\n", - " ]:\n", - " print(acc, ': ', spot.acc_code(acc), sep='')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "all: t\n", - "t: t\n", - "Buchi: Inf(0)\n", - "generalized-Buchi 3: Inf(0)&Inf(1)&Inf(2)\n", - "generalized-Buchi 0: t\n", - "co-Buchi: Fin(0)\n", - "generalized-co-Buchi 3: Fin(0)|Fin(1)|Fin(2)\n", - "generalized-co-Buchi 0: f\n", - "Rabin 2: (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", - "Rabin 0: f\n", - "Streett 2: (Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n", - "Streett 0: t\n", - "generalized-Rabin 3 1 2 3: (Fin(0) & Inf(1)) | (Fin(2) & (Inf(3)&Inf(4))) | (Fin(5) & (Inf(6)&Inf(7)&Inf(8)))\n", - "generalized-Rabin 0: f\n", - "parity min even 6: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & (Inf(4) | Fin(5)))))\n", - "parity max odd 6: Inf(5) | (Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))))\n", - "parity max even 6: Fin(5) & (Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))))\n", - "parity min odd 6: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | (Fin(4) & Inf(5)))))\n", - "parity min even 5: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & Inf(4))))\n", - "parity max odd 5: Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0))))\n", - "parity max even 5: Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0))))\n", - "parity min odd 5: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | Fin(4))))\n", - "parity min even 2: Inf(0) | Fin(1)\n", - "parity max odd 2: Inf(1) | Fin(0)\n", - "parity max even 2: Fin(1) & Inf(0)\n", - "parity min odd 2: Fin(0) & Inf(1)\n", - "parity min even 1: Inf(0)\n", - "parity max odd 1: Fin(0)\n", - "parity max even 1: Inf(0)\n", - "parity min odd 1: Fin(0)\n", - "parity min even 0: t\n", - "parity max odd 0: t\n", - "parity max even 0: f\n", - "parity min odd 0: f\n" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/alternation.ipynb b/tests/python/alternation.ipynb index 4e8ca2119..cc49de118 100644 --- a/tests/python/alternation.ipynb +++ b/tests/python/alternation.ipynb @@ -1,4 +1,1807 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup(show_default='.ba')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These test cases for the `remove_alternation()` algorithm." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "-1->3\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "-4\n", + "\n", + "\n", + "\n", + "1->-4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "-4->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "-4->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.automaton('''\n", + "HOA: v1\n", + "tool: \"ltl3ba\" \"1.1.3\"\n", + "name: \"VWAA for FGa && GFb\"\n", + "States: 6\n", + "Start: 0\n", + "acc-name: co-Buchi\n", + "Acceptance: 1 Fin(0)\n", + "AP: 2 \"a\" \"b\"\n", + "properties: trans-labels explicit-labels state-acc univ-branch very-weak\n", + "--BODY--\n", + "State: 0 \"(FG(a) && GF(b))\"\n", + " [t] 3&1\n", + "State: 1 \"GF(b)\"\n", + " [(1)] 1\n", + " [(!1)] 2&1\n", + "State: 2 \"F(b)\" {0}\n", + " [(1)] 5\n", + " [(!1)] 2\n", + "State: 3 \"FG(a)\" {0}\n", + " [(0)] 4\n", + " [t] 3\n", + "State: 4 \"G(a)\"\n", + " [(0)] 4\n", + "State: 5 \"t\"\n", + " [t] 5\n", + "--END--\n", + "'''); aut.show('.1ab')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1,3\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "1,4\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "1,2,3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "1,2,4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc7e0> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut2 = spot.remove_alternation(aut, True); aut2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1,3\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2\n", + "\n", + "1,4\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3\n", + "\n", + "1,2,3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "4\n", + "\n", + "1,2,4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc1e0> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.scc_filter(aut2, True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & p\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example from ADL's PSL2TGBA talk.\n", + "aut = spot.automaton('''\n", + "HOA: v1\n", + "States: 3\n", + "Start: 0\n", + "acc-name: co-Buchi\n", + "Acceptance: 1 Fin(0)\n", + "AP: 3 \"a\" \"b\" \"p\"\n", + "--BODY--\n", + "State: 0 \"(a;a*;b)*\" {0}\n", + " [0] 1\n", + " [!0] 2\n", + "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", + " [0&1&2] 0&1\n", + " [!1&2] 1\n", + " [!0&!1] 2\n", + " [!0&1&2] 0\n", + "State: 2\n", + " [t] 2\n", + "--END--\n", + "'''); aut.show('.1ab')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "~0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "~1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "{}\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & p\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "~1,~0\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc630> >" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_alternation(aut, True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "I->3\n", + "\n", + "\n", + "\n", + "\n", + "-4\n", + "\n", + "\n", + "\n", + "3->-4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & p\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "-4->0\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "-4->4\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.automaton('''\n", + "HOA: v1\n", + "States: 5\n", + "Start: 3\n", + "acc-name: co-Buchi\n", + "Acceptance: 1 Fin(0)\n", + "AP: 3 \"a\" \"b\" \"p\"\n", + "--BODY--\n", + "State: 0 \"(a;a*;b)*\" {0}\n", + " [0] 1\n", + " [!0] 2\n", + "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", + " [0&1&2] 0&1\n", + " [!1&2] 1\n", + " [!0&!1] 2\n", + " [!0&1&2] 0\n", + "State: 2\n", + " [t] 2\n", + "State: 3\n", + " [0] 4&0\n", + "State: 4\n", + " [t] 3\n", + "--END--\n", + "'''); aut.show('.1ab')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "3\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "~0,4\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "3,~1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3\n", + "\n", + "4,~1,~0\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "4\n", + "\n", + "0,4,~1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "5\n", + "\n", + "3,~0\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "6\n", + "\n", + "3,~1,~0\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc6f0> >" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_alternation(aut, True)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "-7\n", + "\n", + "\n", + "\n", + "I->-7\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "-7->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "-7->3\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "-4\n", + "\n", + "\n", + "\n", + "3->-4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & p\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "1->-1\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "-4->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "-4->4\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example from ADL's PSL2TGBA talk.\n", + "aut = spot.automaton('''\n", + "HOA: v1\n", + "States: 6\n", + "Start: 0&3\n", + "Acceptance: 1 Fin(0)\n", + "AP: 3 \"a\" \"b\" \"p\"\n", + "--BODY--\n", + "State: 0 \"(a;a*;b)*\" {0}\n", + " [0] 1\n", + " [!0] 2\n", + "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", + " [0&1&2] 0&1\n", + " [!1&2] 1\n", + " [!0&!1] 2\n", + " [!0&1&2] 0\n", + "State: 2\n", + " [t] 2\n", + "State: 3\n", + " [0] 3\n", + " [!0] 3&4\n", + "State: 4 {0}\n", + " [!0] 4\n", + " [0] 5\n", + "State: 5\n", + " [t] 5\n", + "--END--\n", + "'''); aut.show('.1ab')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "~0,3\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "3,~1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "3,4\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "3,4,~1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & !b & p\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "3,4,~0\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "3,~1,~0\n", + "\n", + "\n", + "1->6\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a & !b & p\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "\n", + "5->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "6->1\n", + "\n", + "\n", + "a & !b & p\n", + "\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "!a & b & p\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & p\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc7b0> >" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_alternation(aut, True)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "GF(a)\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "-1\n", + "\n", + "\n", + "\n", + "0->-1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "-1->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "F(a)\n", + "\n", + "\n", + "\n", + "-1->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "t\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fcae0> >" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.automaton('''\n", + "HOA: v1\n", + "tool: \"ltl3dra\" \"0.2.2\"\n", + "name: \"VWAA for GFa\"\n", + "States: 3\n", + "Start: 0\n", + "acc-name: co-Buchi\n", + "Acceptance: 1 Fin(0)\n", + "AP: 1 \"a\"\n", + "properties: trans-labels explicit-labels state-acc univ-branch very-weak\n", + "--BODY--\n", + "State: 0 \"GF(a)\"\n", + " [t] 1&0\n", + "State: 1 \"F(a)\" {0}\n", + " [(0)] 2\n", + " [t] 1\n", + "State: 2 \"t\"\n", + " [t] 2\n", + "--END--\n", + "'''); a" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f79685fc840> >" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_alternation(a, True)" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,1795 +1819,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": true, - "input": [ - "import spot\n", - "spot.setup(show_default='.ba')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These test cases for the `remove_alternation()` algorithm." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton('''\n", - "HOA: v1\n", - "tool: \"ltl3ba\" \"1.1.3\"\n", - "name: \"VWAA for FGa && GFb\"\n", - "States: 6\n", - "Start: 0\n", - "acc-name: co-Buchi\n", - "Acceptance: 1 Fin(0)\n", - "AP: 2 \"a\" \"b\"\n", - "properties: trans-labels explicit-labels state-acc univ-branch very-weak\n", - "--BODY--\n", - "State: 0 \"(FG(a) && GF(b))\"\n", - " [t] 3&1\n", - "State: 1 \"GF(b)\"\n", - " [(1)] 1\n", - " [(!1)] 2&1\n", - "State: 2 \"F(b)\" {0}\n", - " [(1)] 5\n", - " [(!1)] 2\n", - "State: 3 \"FG(a)\" {0}\n", - " [(0)] 4\n", - " [t] 3\n", - "State: 4 \"G(a)\"\n", - " [(0)] 4\n", - "State: 5 \"t\"\n", - " [t] 5\n", - "--END--\n", - "'''); aut.show('.1ab')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u24ff\n", - "\n", - "\n", - "-1->3\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "-4\n", - "\n", - "\n", - "\n", - "1->-4\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "-4->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u24ff\n", - "\n", - "\n", - "-4->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut2 = spot.remove_alternation(aut, True); aut2" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1,3\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "1,4\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3\n", - "\n", - "1,2,3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "1,2,4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b\n", - "\u2776\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & !b\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc7e0> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.scc_filter(aut2, True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1,3\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2\n", - "\n", - "1,4\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3\n", - "\n", - "1,2,3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "4\n", - "\n", - "1,2,4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc1e0> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Example from ADL's PSL2TGBA talk.\n", - "aut = spot.automaton('''\n", - "HOA: v1\n", - "States: 3\n", - "Start: 0\n", - "acc-name: co-Buchi\n", - "Acceptance: 1 Fin(0)\n", - "AP: 3 \"a\" \"b\" \"p\"\n", - "--BODY--\n", - "State: 0 \"(a;a*;b)*\" {0}\n", - " [0] 1\n", - " [!0] 2\n", - "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", - " [0&1&2] 0&1\n", - " [!1&2] 1\n", - " [!0&!1] 2\n", - " [!0&1&2] 0\n", - "State: 2\n", - " [t] 2\n", - "--END--\n", - "'''); aut.show('.1ab')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & p\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_alternation(aut, True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "~0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "~1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "{}\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & p\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "~1,~0\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & !b & p\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc630> >" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton('''\n", - "HOA: v1\n", - "States: 5\n", - "Start: 3\n", - "acc-name: co-Buchi\n", - "Acceptance: 1 Fin(0)\n", - "AP: 3 \"a\" \"b\" \"p\"\n", - "--BODY--\n", - "State: 0 \"(a;a*;b)*\" {0}\n", - " [0] 1\n", - " [!0] 2\n", - "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", - " [0&1&2] 0&1\n", - " [!1&2] 1\n", - " [!0&!1] 2\n", - " [!0&1&2] 0\n", - "State: 2\n", - " [t] 2\n", - "State: 3\n", - " [0] 4&0\n", - "State: 4\n", - " [t] 3\n", - "--END--\n", - "'''); aut.show('.1ab')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 7, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "I->3\n", - "\n", - "\n", - "\n", - "\n", - "-4\n", - "\n", - "\n", - "\n", - "3->-4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & p\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "-4->0\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "-4->4\n", - "\n", - "\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_alternation(aut, True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "3\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "~0,4\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "3,~1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3\n", - "\n", - "4,~1,~0\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "4\n", - "\n", - "0,4,~1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b & p\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "a & !b & p\n", - "\n", - "\n", - "5\n", - "\n", - "3,~0\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "6\n", - "\n", - "3,~1,~0\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "a & !b & p\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "a & !b & p\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc6f0> >" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Example from ADL's PSL2TGBA talk.\n", - "aut = spot.automaton('''\n", - "HOA: v1\n", - "States: 6\n", - "Start: 0&3\n", - "Acceptance: 1 Fin(0)\n", - "AP: 3 \"a\" \"b\" \"p\"\n", - "--BODY--\n", - "State: 0 \"(a;a*;b)*\" {0}\n", - " [0] 1\n", - " [!0] 2\n", - "State: 1 \"a*;b;(a;a*;b)*\" {0}\n", - " [0&1&2] 0&1\n", - " [!1&2] 1\n", - " [!0&!1] 2\n", - " [!0&1&2] 0\n", - "State: 2\n", - " [t] 2\n", - "State: 3\n", - " [0] 3\n", - " [!0] 3&4\n", - "State: 4 {0}\n", - " [!0] 4\n", - " [0] 5\n", - "State: 5\n", - " [t] 5\n", - "--END--\n", - "'''); aut.show('.1ab')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "-7\n", - "\n", - "\n", - "\n", - "I->-7\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "-7->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "-7->3\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "-4\n", - "\n", - "\n", - "\n", - "3->-4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & p\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "1->-1\n", - "\n", - "\n", - "a & b & p\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "-4->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u24ff\n", - "\n", - "\n", - "-4->4\n", - "\n", - "\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_alternation(aut, True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "~0,3\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "3,~1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "2\n", - "\n", - "3,4\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & p\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4\n", - "\n", - "3,4,~1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & !b & p\n", - "\u2776\n", - "\n", - "\n", - "5\n", - "\n", - "3,4,~0\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "!a & b & p\n", - "\u2776\n", - "\n", - "\n", - "6\n", - "\n", - "3,~1,~0\n", - "\n", - "\n", - "1->6\n", - "\n", - "\n", - "a & b & p\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "a & !b & p\n", - "\u2776\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a & !b & p\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "!a & b & p\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "a & b & p\n", - "\u2776\n", - "\n", - "\n", - "5->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "6->1\n", - "\n", - "\n", - "a & !b & p\n", - "\u2776\n", - "\n", - "\n", - "6->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "!a & b & p\n", - "\u2776\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & p\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc7b0> >" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.automaton('''\n", - "HOA: v1\n", - "tool: \"ltl3dra\" \"0.2.2\"\n", - "name: \"VWAA for GFa\"\n", - "States: 3\n", - "Start: 0\n", - "acc-name: co-Buchi\n", - "Acceptance: 1 Fin(0)\n", - "AP: 1 \"a\"\n", - "properties: trans-labels explicit-labels state-acc univ-branch very-weak\n", - "--BODY--\n", - "State: 0 \"GF(a)\"\n", - " [t] 1&0\n", - "State: 1 \"F(a)\" {0}\n", - " [(0)] 2\n", - " [t] 1\n", - "State: 2 \"t\"\n", - " [t] 2\n", - "--END--\n", - "'''); a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "GF(a)\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "-1\n", - "\n", - "\n", - "\n", - "0->-1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "-1->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "F(a)\n", - "\u24ff\n", - "\n", - "\n", - "-1->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2\n", - "\n", - "t\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fcae0> >" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_alternation(a, True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "0,1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f79685fc840> >" - ] - } - ], - "prompt_number": 12 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/atva16-fig2a.ipynb b/tests/python/atva16-fig2a.ipynb index 0e0e3038a..08fa4509e 100644 --- a/tests/python/atva16-fig2a.ipynb +++ b/tests/python/atva16-fig2a.ipynb @@ -1,4 +1,228 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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*\"." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup(show_default='.abr')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{G} \\mathsf{F} a \\leftrightarrow \\mathsf{G} \\mathsf{F} b$" + ], + "text/plain": [ + "GFa <-> GFb" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('GFa <-> GFb'); f" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f0d2406cc00> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.translate()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def implies(f, g):\n", + " f = spot.formula(f)\n", + " g = spot.formula_Not(spot.formula(g))\n", + " return spot.product(f.translate(), g.translate()).is_empty()\n", + "def equiv(f, g):\n", + " return implies(f, g) and implies(g, f)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "equiv('a U (b U a)', 'b U a')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "equiv('!(a U b)', '!a U !b')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,230 +240,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example is the left part of Fig.2 in our ATVA'16 paper titled \"*Spot 2.0 \u2014 a framework for LTL and \u03c9-automata manipulation*\"." - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "import spot\n", - "spot.setup(show_default='.abr')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('GFa <-> GFb'); f" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{G} \\mathsf{F} a \\leftrightarrow \\mathsf{G} \\mathsf{F} b$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "GFa <-> GFb" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.translate()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!a & b\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f0d2406cc00> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "def implies(f, g):\n", - " f = spot.formula(f)\n", - " g = spot.formula_Not(spot.formula(g))\n", - " return spot.product(f.translate(), g.translate()).is_empty()\n", - "def equiv(f, g):\n", - " return implies(f, g) and implies(g, f)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "equiv('a U (b U a)', 'b U a')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "True" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "equiv('!(a U b)', '!a U !b')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "text": [ - "False" - ] - } - ], - "prompt_number": 6 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/atva16-fig2b.ipynb b/tests/python/atva16-fig2b.ipynb index f896ac9de..7184ea66f 100644 --- a/tests/python/atva16-fig2b.ipynb +++ b/tests/python/atva16-fig2b.ipynb @@ -1,4 +1,322 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example is the right part of Fig.2 in our ATVA'16 paper titled \"*Spot 2.0 — a framework for LTL and ω-automata manipulation*\"." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import spot\n", + "import spot.ltsmin\n", + "spot.setup(show_default='.abr', max_states=10)\n", + "# This extra line ensures that our test-suite skips this test if divine is not installed.\n", + "spot.ltsmin.require('divine')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%dve adding\n", + "int c=1, x1, x2;\n", + "process a1 {\n", + " state Q, R, S; init Q;\n", + " trans Q -> R { guard c<20; effect x1 = c; },\n", + " R -> S { effect x1 = x1 + c; },\n", + " S -> Q { effect c = x1; };\n", + "}\n", + "process a2 {\n", + " state Q, R, S; init Q;\n", + " trans Q -> R { guard c<20; effect x2 = c; },\n", + " R -> S { effect x2 = x2 + c; },\n", + " S -> Q { effect c = x2; };\n", + "}\n", + "system async;" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ltsmin model with the following variables:\n", + " c: int\n", + " x1: int\n", + " x2: int\n", + " a1: ['Q', 'R', 'S']\n", + " a2: ['Q', 'R', 'S']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adding" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "0\n", + "\n", + "c=1, x1=0, x2=0, a1=0, a2=0\n", + "a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "c=1, x1=1, x2=0, a1=1, a2=0\n", + "!a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "c=1, x1=0, x2=1, a1=0, a2=1\n", + "a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "c=1, x1=2, x2=0, a1=2, a2=0\n", + "!a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "c=1, x1=1, x2=1, a1=1, a2=1\n", + "!a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "c=1, x1=0, x2=2, a1=0, a2=2\n", + "a1.Q & !"c==17" & !dead\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "c=2, x1=2, x2=0, a1=0, a2=0\n", + "...\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "c=1, x1=2, x2=1, a1=2, a2=1\n", + "...\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "c=1, x1=1, x2=2, a1=1, a2=2\n", + "...\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "c=2, x1=0, x2=2, a1=0, a2=0\n", + "...\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "\n", + "\n", + "u6\n", + "\n", + "...\n", + "\n", + "\n", + "6->u6\n", + "\n", + "\n", + "\n", + "\n", + "u7\n", + "\n", + "...\n", + "\n", + "\n", + "7->u7\n", + "\n", + "\n", + "\n", + "\n", + "u8\n", + "\n", + "...\n", + "\n", + "\n", + "8->u8\n", + "\n", + "\n", + "\n", + "\n", + "u9\n", + "\n", + "...\n", + "\n", + "\n", + "9->u9\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb770097600> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adding.kripke(['a1.Q', 'c==17'])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def model_check(model, f):\n", + " f = spot.formula(f)\n", + " ss = model.kripke(spot.atomic_prop_collect(f))\n", + " nf = spot.formula_Not(f).translate()\n", + " return spot.otf_product(ss, nf).is_empty()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model_check(adding, 'F(\"c==2\")')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,326 +334,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example is the right part of Fig.2 in our ATVA'16 paper titled \"*Spot 2.0 \u2014 a framework for LTL and \u03c9-automata manipulation*\"." - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "import spot\n", - "import spot.ltsmin\n", - "spot.setup(show_default='.abr', max_states=10)\n", - "# This extra line ensures that our test-suite skips this test if divine is not installed.\n", - "spot.ltsmin.require('divine')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "%%dve adding\n", - "int c=1, x1, x2;\n", - "process a1 {\n", - " state Q, R, S; init Q;\n", - " trans Q -> R { guard c<20; effect x1 = c; },\n", - " R -> S { effect x1 = x1 + c; },\n", - " S -> Q { effect c = x1; };\n", - "}\n", - "process a2 {\n", - " state Q, R, S; init Q;\n", - " trans Q -> R { guard c<20; effect x2 = c; },\n", - " R -> S { effect x2 = x2 + c; },\n", - " S -> Q { effect c = x2; };\n", - "}\n", - "system async;" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "adding" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "ltsmin model with the following variables:\n", - " c: int\n", - " x1: int\n", - " x2: int\n", - " a1: ['Q', 'R', 'S']\n", - " a2: ['Q', 'R', 'S']" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "adding.kripke(['a1.Q', 'c==17'])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "t\n", - "[all]\n", - "\n", - "\n", - "0\n", - "\n", - "c=1, x1=0, x2=0, a1=0, a2=0\n", - "a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "c=1, x1=1, x2=0, a1=1, a2=0\n", - "!a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "c=1, x1=0, x2=1, a1=0, a2=1\n", - "a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "c=1, x1=2, x2=0, a1=2, a2=0\n", - "!a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "c=1, x1=1, x2=1, a1=1, a2=1\n", - "!a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "c=1, x1=0, x2=2, a1=0, a2=2\n", - "a1.Q & !"c==17" & !dead\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "c=2, x1=2, x2=0, a1=0, a2=0\n", - "...\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "c=1, x1=2, x2=1, a1=2, a2=1\n", - "...\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "c=1, x1=1, x2=2, a1=1, a2=2\n", - "...\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "c=2, x1=0, x2=2, a1=0, a2=0\n", - "...\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "\n", - "\n", - "u6\n", - "\n", - "...\n", - "\n", - "\n", - "6->u6\n", - "\n", - "\n", - "\n", - "\n", - "u7\n", - "\n", - "...\n", - "\n", - "\n", - "7->u7\n", - "\n", - "\n", - "\n", - "\n", - "u8\n", - "\n", - "...\n", - "\n", - "\n", - "8->u8\n", - "\n", - "\n", - "\n", - "\n", - "u9\n", - "\n", - "...\n", - "\n", - "\n", - "9->u9\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb770097600> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "def model_check(model, f):\n", - " f = spot.formula(f)\n", - " ss = model.kripke(spot.atomic_prop_collect(f))\n", - " nf = spot.formula_Not(f).translate()\n", - " return spot.otf_product(ss, nf).is_empty()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "model_check(adding, 'F(\"c==2\")')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "text": [ - "True" - ] - } - ], - "prompt_number": 6 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/automata-io.ipynb b/tests/python/automata-io.ipynb index 25adc2ee7..9304361d0 100644 --- a/tests/python/automata-io.ipynb +++ b/tests/python/automata-io.ipynb @@ -1,4 +1,829 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "AP: 2 \"a\" \"b\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "properties: trans-labels explicit-labels state-acc deterministic\n", + "properties: stutter-invariant terminal\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "State: 1\n", + "[1] 0\n", + "[0&!1] 1\n", + "--END--\n", + "never {\n", + "T0_init:\n", + " if\n", + " :: (b) -> goto accept_all\n", + " :: ((a) && (!(b))) -> goto T0_init\n", + " fi;\n", + "accept_all:\n", + " skip\n", + "}\n", + "\n", + "digraph G {\n", + " rankdir=LR\n", + " node [shape=\"circle\"]\n", + " node [style=\"filled\", fillcolor=\"#ffffaa\"]\n", + " fontname=\"Lato\"\n", + " node [fontname=\"Lato\"]\n", + " edge [fontname=\"Lato\"]\n", + " size=\"10.2,5\" edge[arrowhead=vee, arrowsize=.7]\n", + " I [label=\"\", style=invis, width=0]\n", + " I -> 1\n", + " 0 [label=<0>, peripheries=2]\n", + " 0 -> 0 [label=<1>]\n", + " 1 [label=<1>]\n", + " 1 -> 0 [label=]\n", + " 1 -> 1 [label=]\n", + "}\n", + "\n", + "2 1\n", + "0 1 -1\n", + "1 \"b\"\n", + "0 & \"a\" ! \"b\"\n", + "-1\n", + "1 0 0 -1\n", + "1 t\n", + "-1\n", + "\n" + ] + } + ], + "source": [ + "a = spot.translate('a U b')\n", + "for fmt in ('hoa', 'spin', 'dot', 'lbtt'):\n", + " print(a.to_str(fmt))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c050a20> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.save('example.aut').save('example.aut', format='lbtt', append=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HOA: v1\r\n", + "States: 2\r\n", + "Start: 1\r\n", + "AP: 2 \"a\" \"b\"\r\n", + "acc-name: Buchi\r\n", + "Acceptance: 1 Inf(0)\r\n", + "properties: trans-labels explicit-labels state-acc deterministic\r\n", + "properties: stutter-invariant terminal\r\n", + "--BODY--\r\n", + "State: 0 {0}\r\n", + "[t] 0\r\n", + "State: 1\r\n", + "[1] 0\r\n", + "[0&!1] 1\r\n", + "--END--\r\n", + "2 1\r\n", + "0 1 -1\r\n", + "1 \"b\"\r\n", + "0 & \"a\" ! \"b\"\r\n", + "-1\r\n", + "1 0 0 -1\r\n", + "1 t\r\n", + "-1\r\n" + ] + } + ], + "source": [ + "!cat example.aut" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195f3ecab0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c050960> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for a in spot.automata('example.aut'):\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test `--ABORT--`\n", + "----------------" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting example.aut\n" + ] + } + ], + "source": [ + "%%file example.aut\n", + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "AP: 2 \"a\" \"b\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "--ABORT-- /* the previous automaton should be ignored */\n", + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "State: 1\n", + "[1] 0\n", + "[0&!1] 1\n", + "--END--" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c050a50> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for a in spot.automata('example.aut'):\n", + " display(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c086120> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c050900> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for a in spot.automata(\"\"\"\n", + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "name: \"Hello world\"\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "State: 1\n", + "[1] 0\n", + "[0&!1] 1\n", + "--END--\n", + "HOA: v1\n", + "States: 1\n", + "Start: 0\n", + "name: \"Hello world 2\"\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 2 Inf(0)&Inf(1)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0 {1}\n", + "[0&!1] 0\n", + "--END--\n", + "\"\"\"):\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test syntax errors\n", + "------------------" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting example.aut\n" + ] + } + ], + "source": [ + "%%file example.aut\n", + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "AP: 2 \"a\" \"b\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 1\n", + "State: 1\n", + "[t] 1\n", + "--END--\n", + "HOA: v1\n", + "States: 2\n", + "Start: 1\n", + "AP: 2 \"a\" \"b\"\n", + "Acceptance: 1 Inf(0)\n", + "--BODY--\n", + "State: 0 {0}\n", + "[a] 3\n", + "State: 1\n", + "[1] 0\n", + "[0&!1] 1\n", + "--END--" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c0860c0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "SyntaxError", + "evalue": "\nexample.aut:20.2: syntax error, unexpected identifier\nexample.aut:20.1-3: ignoring this invalid label\nexample.aut:20.5: state number is larger than state count...\nexample.aut:14.1-9: ... declared here.\n ()", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \nexample.aut:20.2: syntax error, unexpected identifier\nexample.aut:20.1-3: ignoring this invalid label\nexample.aut:20.5: state number is larger than state count...\nexample.aut:14.1-9: ... declared here.\n\n" + ] + } + ], + "source": [ + "for a in spot.automata('example.aut'):\n", + " display(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f195c086600> >" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('example.aut', timeout=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "ename": "CalledProcessError", + "evalue": "Command 'non-existing-cmd ' returned non-zero exit status 127.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'non-existing-cmd |'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 479\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 480\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 481\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 482\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 483\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 464\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 466\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 467\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 468\u001b[0m \u001b[0;31m# reporting the following error: \"\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'sleep 3; cat example.aut |'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 479\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 480\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 481\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 482\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 483\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 423\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 424\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 425\u001b[0;31m \u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcommunicate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 426\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTimeoutExpired\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0;31m# Using subprocess.check_output() with timeout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/subprocess.py\u001b[0m in \u001b[0;36mcommunicate\u001b[0;34m(self, input, timeout)\u001b[0m\n\u001b[1;32m 841\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 842\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 843\u001b[0;31m \u001b[0mstdout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstderr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_communicate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mendtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 844\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 845\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_communication_started\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/subprocess.py\u001b[0m in \u001b[0;36m_communicate\u001b[0;34m(self, input, endtime, orig_timeout)\u001b[0m\n\u001b[1;32m 1513\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1514\u001b[0m \u001b[0mready\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mselector\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mselect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1515\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_timeout\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mendtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morig_timeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1516\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1517\u001b[0m \u001b[0;31m# XXX Rewrite these to use non-blocking I/O on the file\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/subprocess.py\u001b[0m in \u001b[0;36m_check_timeout\u001b[0;34m(self, endtime, orig_timeout)\u001b[0m\n\u001b[1;32m 869\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 870\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m_time\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0mendtime\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 871\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTimeoutExpired\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morig_timeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 872\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 873\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTimeoutExpired\u001b[0m: Command 'sleep 3; cat example.aut ' timed out after 1 seconds" + ] + } + ], + "source": [ + "spot.automaton('sleep 3; cat example.aut |', timeout=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "rm example.aut" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -15,851 +840,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3+" - }, - "name": "", - "signature": "sha256:d9763e3af9f29bca127bdbfb9c6b0bcfaf276a0c32d9f789d696bfbe4a563e57" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display\n", - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('a U b')\n", - "for fmt in ('hoa', 'spin', 'dot', 'lbtt'):\n", - " print(a.to_str(fmt))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "AP: 2 \"a\" \"b\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "properties: trans-labels explicit-labels state-acc deterministic\n", - "properties: stutter-invariant terminal\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "State: 1\n", - "[1] 0\n", - "[0&!1] 1\n", - "--END--\n", - "never {\n", - "T0_init:\n", - " if\n", - " :: (b) -> goto accept_all\n", - " :: ((a) && (!(b))) -> goto T0_init\n", - " fi;\n", - "accept_all:\n", - " skip\n", - "}\n", - "\n", - "digraph G {\n", - " rankdir=LR\n", - " node [shape=\"circle\"]\n", - " node [style=\"filled\", fillcolor=\"#ffffaa\"]\n", - " fontname=\"Lato\"\n", - " node [fontname=\"Lato\"]\n", - " edge [fontname=\"Lato\"]\n", - " size=\"10.2,5\" edge[arrowhead=vee, arrowsize=.7]\n", - " I [label=\"\", style=invis, width=0]\n", - " I -> 1\n", - " 0 [label=<0>, peripheries=2]\n", - " 0 -> 0 [label=<1>]\n", - " 1 [label=<1>]\n", - " 1 -> 0 [label=]\n", - " 1 -> 1 [label=]\n", - "}\n", - "\n", - "2 1\n", - "0 1 -1\n", - "1 \"b\"\n", - "0 & \"a\" ! \"b\"\n", - "-1\n", - "1 0 0 -1\n", - "1 t\n", - "-1\n", - "\n" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.save('example.aut').save('example.aut', format='lbtt', append=True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201e0810> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!cat example.aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "HOA: v1\r\n", - "States: 2\r\n", - "Start: 1\r\n", - "AP: 2 \"a\" \"b\"\r\n", - "acc-name: Buchi\r\n", - "Acceptance: 1 Inf(0)\r\n", - "properties: trans-labels explicit-labels state-acc deterministic\r\n", - "properties: stutter-invariant terminal\r\n", - "--BODY--\r\n", - "State: 0 {0}\r\n", - "[t] 0\r\n", - "State: 1\r\n", - "[1] 0\r\n", - "[0&!1] 1\r\n", - "--END--\r\n", - "2 1\r\n", - "0 1 -1\r\n", - "1 \"b\"\r\n", - "0 & \"a\" ! \"b\"\r\n", - "-1\r\n", - "1 0 0 -1\r\n", - "1 t\r\n", - "-1\r\n" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata('example.aut'):\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201e09c0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201ff1b0> >" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Test `--ABORT--`\n", - "----------------" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%file example.aut\n", - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "AP: 2 \"a\" \"b\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "--ABORT-- /* the previous automaton should be ignored */\n", - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "State: 1\n", - "[1] 0\n", - "[0&!1] 1\n", - "--END--" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Overwriting example.aut\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata('example.aut'):\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201e0900> >" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata(\"\"\"\n", - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "name: \"Hello world\"\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "State: 1\n", - "[1] 0\n", - "[0&!1] 1\n", - "--END--\n", - "HOA: v1\n", - "States: 1\n", - "Start: 0\n", - "name: \"Hello world 2\"\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 2 Inf(0)&Inf(1)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0 {1}\n", - "[0&!1] 0\n", - "--END--\n", - "\"\"\"):\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201ff1b0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201e0900> >" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Test syntax errors\n", - "------------------" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%file example.aut\n", - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "AP: 2 \"a\" \"b\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 1\n", - "State: 1\n", - "[t] 1\n", - "--END--\n", - "HOA: v1\n", - "States: 2\n", - "Start: 1\n", - "AP: 2 \"a\" \"b\"\n", - "Acceptance: 1 Inf(0)\n", - "--BODY--\n", - "State: 0 {0}\n", - "[a] 3\n", - "State: 1\n", - "[1] 0\n", - "[0&!1] 1\n", - "--END--" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Overwriting example.aut\n" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata('example.aut'):\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201ff390> >" - ] - }, - { - "ename": "SyntaxError", - "evalue": "\nexample.aut:20.2: syntax error, unexpected identifier\nexample.aut:20.1-3: ignoring this invalid label\nexample.aut:20.5: state number is larger than state count...\nexample.aut:14.1-9: ... declared here.\n ()", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \nexample.aut:20.2: syntax error, unexpected identifier\nexample.aut:20.1-3: ignoring this invalid label\nexample.aut:20.5: state number is larger than state count...\nexample.aut:14.1-9: ... declared here.\n\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('example.aut', timeout=100)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f45201ff270> >" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('non-existing-cmd |')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "CalledProcessError", - "evalue": "Command 'non-existing-cmd ' returned non-zero exit status 127", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'non-existing-cmd |'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 471\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 472\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 473\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 474\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 475\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, debug, *sources)\u001b[0m\n\u001b[1;32m 456\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 457\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 458\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 459\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 460\u001b[0m \u001b[0;31m# reporting the following error: \"\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'sleep 3; cat example.aut |'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 471\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 472\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 473\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 474\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 475\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, debug, *sources)\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 416\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 417\u001b[0;31m \u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcommunicate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 418\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTimeoutExpired\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 419\u001b[0m \u001b[0;31m# Using subprocess.check_output() with timeout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/lib/python3.5/subprocess.py\u001b[0m in \u001b[0;36mcommunicate\u001b[0;34m(self, input, timeout)\u001b[0m\n\u001b[1;32m 1063\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1064\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1065\u001b[0;31m \u001b[0mstdout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstderr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_communicate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mendtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1066\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1067\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_communication_started\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/lib/python3.5/subprocess.py\u001b[0m in \u001b[0;36m_communicate\u001b[0;34m(self, input, endtime, orig_timeout)\u001b[0m\n\u001b[1;32m 1698\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1699\u001b[0m \u001b[0mready\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mselector\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mselect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1700\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_timeout\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mendtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morig_timeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1701\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1702\u001b[0m \u001b[0;31m# XXX Rewrite these to use non-blocking I/O on the file\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/lib/python3.5/subprocess.py\u001b[0m in \u001b[0;36m_check_timeout\u001b[0;34m(self, endtime, orig_timeout)\u001b[0m\n\u001b[1;32m 1089\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1090\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m_time\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0mendtime\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1091\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTimeoutExpired\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morig_timeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1092\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1093\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTimeoutExpired\u001b[0m: Command 'sleep 3; cat example.aut ' timed out after 1 seconds" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "rm example.aut" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 14 - } - ], - "metadata": {} + "version": "3.6.4" } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/automata.ipynb b/tests/python/automata.ipynb index 89272b53a..3ab2d982a 100644 --- a/tests/python/automata.ipynb +++ b/tests/python/automata.ipynb @@ -1,4 +1,3637 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1043b73f0> >" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.translate('(a U b) & GFc & GFd', 'BA', 'complete'); a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The call the `spot.setup()` in the first cells has installed a default style for the graphviz output. If you want to change this style temporarily, you can call the `show(style)` method explicitely. For instance here is a vertical layout with the default font of GraphViz." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.show(\"v\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to add some style options to the existing one, pass a dot to the `show()` function in addition to your own style options:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.show(\".ast\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `translate()` function can also be called with a formula object. Either as a function, or as a method." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$a \\mathbin{\\mathsf{U}} b$" + ], + "text/plain": [ + "a U b" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('a U b'); f" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042bc900> >" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.translate(f)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce7b0> >" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.translate()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When used as a method, all the arguments are translation options. Here is a monitor:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1043b7390> >" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.translate('mon')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following three cells show a formulas for which it makes a difference to select `'small'` or `'deterministic'`." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{G} a \\lor \\mathsf{G} b \\lor \\mathsf{G} c$" + ], + "text/plain": [ + "Ga | Gb | Gc" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('Ga | Gb | Gc'); f" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.translate('ba', 'small').show('.v')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "I->6\n", + "\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "6->0\n", + "\n", + "\n", + "!a & !b & c\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "6->1\n", + "\n", + "\n", + "!a & b & c\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "!a & b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.translate('ba', 'det').show('v.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is how to build an unambiguous automaton:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce870> >" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.translate('GFa -> GFb', 'unambig')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare with the standard translation:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042bc660> >" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.translate('GFa -> GFb')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And here is the automaton above with state-based acceptance:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce6c0> >" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.translate('GFa -> GFb', 'sbacc')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some example of running the self-loopization algorithm on an automaton:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1043dd600> >" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.translate('F(a & X(!a &Xb))', \"any\"); a" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "0->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "0->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "9\n", + "\n", + "9\n", + "\n", + "\n", + "7->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "10\n", + "\n", + "10\n", + "\n", + "\n", + "7->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "8->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "8->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "9->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "9->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "11\n", + "\n", + "11\n", + "\n", + "\n", + "9->11\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "12\n", + "\n", + "12\n", + "\n", + "\n", + "9->12\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "10->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "10->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "10->11\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "10->12\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "11->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "11->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "11->11\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "11->12\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "12->9\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "12->10\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "12->11\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "12->12\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce600> >" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.sl(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.is_empty()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reading from file (see `automaton-io.ipynb` for more examples)." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing example1.aut\n" + ] + } + ], + "source": [ + "%%file example1.aut\n", + "HOA: v1\n", + "States: 3\n", + "Start: 0\n", + "AP: 2 \"a\" \"b\"\n", + "acc-name: Buchi\n", + "Acceptance: 4 Inf(0)&Fin(1)&Fin(3) | Inf(2)&Inf(3) | Inf(1)\n", + "--BODY--\n", + "State: 0 {3}\n", + "[t] 0\n", + "[0] 1 {1}\n", + "[!0] 2 {0}\n", + "State: 1 {3}\n", + "[1] 0\n", + "[0&1] 1 {0}\n", + "[!0&1] 2 {2}\n", + "State: 2\n", + "[!1] 0\n", + "[0&!1] 1 {0}\n", + "[!0&!1] 2 {0}\n", + "--END--" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | Inf(\n", + "\n", + ") | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "[Fin-less 4]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042bc8d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "a = spot.automaton('example1.aut')\n", + "display(a.show('.a'))\n", + "display(spot.remove_fin(a).show('.a'))\n", + "display(a.postprocess('TGBA', 'complete').show('.a'))\n", + "display(a.postprocess('BA'))" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!rm example1.aut" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce780> >" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.complete(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce8a0> >" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.complete(spot.translate('Ga'))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "1,0\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Using +1 in the display options is a convient way to shift the \n", + "# set numbers in the output, as an aid in reading the product.\n", + "a1 = spot.translate('a W c'); display(a1.show('.bat'))\n", + "a2 = spot.translate('a U b'); display(a2.show('.bat+1'))\n", + "# the product should display pairs of states, unless asked not to (using 1).\n", + "p = spot.product(a1, a2); display(p.show('.bat')); display(p.show('.bat1'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Explicit determinization after translation:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce810> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "False" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "a = spot.translate('FGa')\n", + "display(a)\n", + "display(a.is_deterministic())" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")\n", + "[Rabin 1]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.tgba_determinize(a).show('.ba')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Determinization by `translate()`. The `generic` option allows any acceptance condition to be used instead of the default generalized Büchi." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce7e0> >" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('FGa', 'generic', 'deterministic'); aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding an atomic proposition to all edges" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce7e0> >" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import buddy\n", + "b = buddy.bdd_ithvar(aut.register_ap('b'))\n", + "for e in aut.edges():\n", + " e.cond &= b\n", + "aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding an atomic proposition to the edge between 0 and 1:" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb1042ce7e0> >" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = buddy.bdd_ithvar(aut.register_ap('c'))\n", + "for e in aut.out(0):\n", + " if e.dst == 1:\n", + " e.cond &= c\n", + "aut" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,3583 +3649,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display\n", - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "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)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('(a U b) & GFc & GFd', 'BA', 'complete'); a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "c & d\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!d\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!c & d\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "c & d\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!d\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!c & d\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1043b73f0> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The call the `spot.setup()` in the first cells has installed a default style for the graphviz output. If you want to change this style temporarily, you can call the `show(style)` method explicitely. For instance here is a vertical layout with the default font of GraphViz." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.show(\"v\")" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "c & d\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!d\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!c & d\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "c & d\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!d\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!c & d\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!c\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you want to add some style options to the existing one, pass a dot to the `show()` function in addition to your own style options:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.show(\".ast\")" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "c & d\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!d\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!c & d\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "c & d\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!d\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!c & d\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `translate()` function can also be called with a formula object. Either as a function, or as a method." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('a U b'); f" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$a \\mathbin{\\mathsf{U}} b$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "a U b" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.translate(f)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042bc900> >" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.translate()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 7, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce7b0> >" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When used as a method, all the arguments are translation options. Here is a monitor:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.translate('mon')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1043b7390> >" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following three cells show a formulas for which it makes a difference to select `'small'` or `'deterministic'`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('Ga | Gb | Gc'); f" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{G} a \\lor \\mathsf{G} b \\lor \\mathsf{G} c$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "Ga | Gb | Gc" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.translate('ba', 'small').show('.v')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3\n", - "\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.translate('ba', 'det').show('v.')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "\n", - "6\n", - "\n", - "\n", - "I->6\n", - "\n", - "\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "6->0\n", - "\n", - "\n", - "!a & !b & c\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "6->1\n", - "\n", - "\n", - "!a & b & c\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "6->2\n", - "\n", - "\n", - "!a & b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "\n", - "3\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & c\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here is how to build an unambiguous automaton:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.translate('GFa -> GFb', 'unambig')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce870> >" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare with the standard translation:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.translate('GFa -> GFb')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042bc660> >" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And here is the automaton above with state-based acceptance:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.translate('GFa -> GFb', 'sbacc')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce6c0> >" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Some example of running the self-loopization algorithm on an automaton:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('F(a & X(!a &Xb))', \"any\"); a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1043dd600> >" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.sl(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "0->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "0->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "9\n", - "\n", - "9\n", - "\n", - "\n", - "7->9\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "10\n", - "\n", - "10\n", - "\n", - "\n", - "7->10\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "8->9\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "8->10\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "9->9\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "9->10\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "11\n", - "\n", - "11\n", - "\n", - "\n", - "9->11\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "12\n", - "\n", - "12\n", - "\n", - "\n", - "9->12\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "10->9\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "10->10\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "10->11\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "10->12\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "11->9\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "11->10\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "11->11\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "11->12\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "12->9\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "12->10\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "12->11\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "12->12\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce600> >" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.is_empty()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 17, - "text": [ - "False" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Reading from file (see `automaton-io.ipynb` for more examples)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%file example1.aut\n", - "HOA: v1\n", - "States: 3\n", - "Start: 0\n", - "AP: 2 \"a\" \"b\"\n", - "acc-name: Buchi\n", - "Acceptance: 4 Inf(0)&Fin(1)&Fin(3) | Inf(2)&Inf(3) | Inf(1)\n", - "--BODY--\n", - "State: 0 {3}\n", - "[t] 0\n", - "[0] 1 {1}\n", - "[!0] 2 {0}\n", - "State: 1 {3}\n", - "[1] 0\n", - "[0&1] 1 {0}\n", - "[!0&1] 2 {2}\n", - "State: 2\n", - "[!1] 0\n", - "[0&!1] 1 {0}\n", - "[!0&!1] 2 {0}\n", - "--END--" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Writing example1.aut\n" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.automaton('example1.aut')\n", - "display(a.show('.a'))\n", - "display(spot.remove_fin(a).show('.a'))\n", - "display(a.postprocess('TGBA', 'complete').show('.a'))\n", - "display(a.postprocess('BA'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "(Inf(\n", - "\u24ff\n", - ") & Fin(\n", - "\u2776\n", - ") & Fin(\n", - "\u2778\n", - ")) | (Inf(\n", - "\u2777\n", - ")&Inf(\n", - "\u2778\n", - ")) | Inf(\n", - "\u2776\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | Inf(\n", - "\u2776\n", - ") | (Inf(\n", - "\u2777\n", - ")&Inf(\n", - "\u2778\n", - "))\n", - "[Fin-less 4]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u2778\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042bc8d0> >" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!rm example1.aut" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 20 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.complete(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 21, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce780> >" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.complete(spot.translate('Ga'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 22, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce8a0> >" - ] - } - ], - "prompt_number": 22 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Using +1 in the display options is a convient way to shift the \n", - "# set numbers in the output, as an aid in reading the product.\n", - "a1 = spot.translate('a W c'); display(a1.show('.bat'))\n", - "a2 = spot.translate('a U b'); display(a2.show('.bat+1'))\n", - "# the product should display pairs of states, unless asked not to (using 1).\n", - "p = spot.product(a1, a2); display(p.show('.bat')); display(p.show('.bat1'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !c\n", - "\u24ff\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "c\n", - "\u24ff\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "1,1\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "0,1\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "1,0\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & b & !c\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & b & !c\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Explicit determinization after translation:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('FGa')\n", - "display(a)\n", - "display(a.is_deterministic())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce810> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "text": [ - "False" - ] - } - ], - "prompt_number": 24 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.tgba_determinize(a).show('.ba')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 25, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")\n", - "[Rabin 1]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Determinization by `translate()`. The `generic` option allows any acceptance condition to be used instead of the default generalized B\u00fcchi." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('FGa', 'generic', 'deterministic'); aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 26, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce7e0> >" - ] - } - ], - "prompt_number": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Adding an atomic proposition to all edges" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import buddy\n", - "b = buddy.bdd_ithvar(aut.register_ap('b'))\n", - "for e in aut.edges():\n", - " e.cond &= b\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 27, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce7e0> >" - ] - } - ], - "prompt_number": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Adding an atomic proposition to the edge between 0 and 1:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "c = buddy.bdd_ithvar(aut.register_ap('c'))\n", - "for e in aut.out(0):\n", - " if e.dst == 1:\n", - " e.cond &= c\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 28, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b & c\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & b\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb1042ce7e0> >" - ] - } - ], - "prompt_number": 28 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/decompose.ipynb b/tests/python/decompose.ipynb index c6c99f630..80a1ecb84 100644 --- a/tests/python/decompose.ipynb +++ b/tests/python/decompose.ipynb @@ -1,4 +1,5454 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "import spot\n", + "spot.setup(show_default='.bans')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook demonstrates how to use the `decompose_scc()` function to split an automaton in up to three automata capturing different behaviors. This is based on the paper [Strength-based decomposition of the property Büchi automaton for faster model checking](https://www.lrde.epita.fr/~adl/dl/adl/renault.13.tacas.pdf) (TACAS'13).\n", + "\n", + "This page uses the Python bindings, but the same decompositions can be performed from the shell using [`autfilt`](https://spot.lrde.epita.fr/autfilt.html) and its `--decompose-scc` option.\n", + "\n", + "# Basics\n", + "\n", + "Let's define the following strengths of accepting SCCs:\n", + "\n", + "- an accepting SCC is **inherently weak** if it does not contain any rejecting cycle\n", + "- an accepting SCC is **inherently terminal** if it is *inherently weak* and complete (i.e. from any state, you can stay in the SCC by reading any word)\n", + "- an accepting SCC is **strictly inherently weak** if it is *inherently weak* and not complete (in other words: *weak* but not *terminal*)\n", + "- an accepting SCC is **strong** if it is not inherently weak.\n", + "\n", + "The strengths **strong**, **stricly inherently weak**, and **inherently terminal** define a partition of all accepting SCCs. The following Büchi automaton has 4 SCCs, and its 3 accepting SCCs show an example of each strength.\n", + "\n", + "Note: the reason we use the word *inherently* is that the *weak* and *terminal* properties are usually defined syntactically: an accepting SCC would be weak if all its transitions belong to the same acceptance sets. This syntactic criterion is a sufficient condition for an accepting SCC to not have any rejecting cycle, but it is not necessary. Hence a *weak* SCC is *inherently weak*; but while an *inherently weak* SCC is not necessarily *weak*, it can be modified to be *weak* without alterning the langage." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc5466510> >" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('(Ga -> Gb) W c')\n", + "aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `decompose_strength()` function takes an automaton, and a string specifying which strength to preserve. \n", + "\n", + "The letters used for this specification are as follows:\n", + "\n", + "- `t`: (inherently) terminal\n", + "- `w`: (strictly inherently) weak\n", + "- `s`: strong\n", + "\n", + "For instance if we want to preserve only the **strictly inherently weak** part of this automaton, we should get only the SCC with the self-loop on $b$, and the SCC above it so that we can reach it. However the SCC above is not stricly weak, so it should not accept any word in the new automaton." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca420> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(aut, 'w')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can extract all the behaviors captured by the **inherently terminal** part of the automaton:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca1b0> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(aut, 't')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the **strong** part:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc5466330> >" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "strong = spot.decompose_scc(aut, 's'); strong" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The union of these three automata recognize the same language as the original automaton.\n", + "\n", + "\n", + "The application proposed in the aforementioned TACAS'13 paper is for parallelizing model checking. Instead of testing the emptiness of the product between `aut` and a system, one could test the emptiness **3** products in parallel: each with a sub-automaton of different strength. Model checking using weak and terminal automata can be done with much more simpler emptiness check procedures than needed for the general case. So in effect, we have isolated the \"hard\" (i.e. strong) part of the original automaton in a smaller automaton, and we only need to use a full-fledged emptiness check for this case.\n", + "\n", + "An additional bonus is that it is possible that the simplification algorithms will do a better job at simplifying the sub-automata than at simplifying the original `aut`. For instance here the `strong` automaton can be further simplified:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca180> >" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "strong.postprocess('small')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multi-strength extraction\n", + "\n", + "The string passed to `decompose_strength()` can include multiple letters to extract multiple strengths at once." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "option: sw\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca360> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "option: st\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca120> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "option: wt\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca390> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for opt in ('sw', 'st', 'wt'):\n", + " a = spot.decompose_scc(aut, opt)\n", + " a.set_name(\"option: \" + opt)\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generalized acceptance\n", + "\n", + "There is nothing that prevents the above decomposition to work with other types of acceptance.\n", + "\n", + "## Rabin\n", + "\n", + "The following Rabin automaton was generated with\n", + "\n", + " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --ltl2nba=spin:ltl2tgba@-Ds' -H | autfilt -H --merge-transitions\n", + " \n", + "(The `autfilt -H --merge-transitions` pass is just here to reduce the size of the file and make the automaton more readable.)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "cluster_5\n", + "\n", + "\n", + "cluster_6\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->6\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "\n", + "8->6\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "8->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "0->6\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "0->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "5->0\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "7->6\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "7->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "7->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "7->0\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "7->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec1e0> >" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.automaton(\"\"\"\n", + "HOA: v1\n", + "States: 9\n", + "Start: 2\n", + "AP: 3 \"a\" \"b\" \"c\"\n", + "acc-name: Rabin 2\n", + "Acceptance: 4 (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", + "properties: trans-labels explicit-labels state-acc complete\n", + "properties: deterministic\n", + "--BODY--\n", + "State: 0 {2}\n", + "[0&!2] 0\n", + "[0&2] 1\n", + "[!0&!2] 5\n", + "[!0&2] 6\n", + "State: 1 {2}\n", + "[0] 1\n", + "[!0] 6\n", + "State: 2 {2}\n", + "[0&!1&!2] 3\n", + "[0&1&!2] 4\n", + "[!0&!2] 5\n", + "[2] 6\n", + "State: 3 {1 2}\n", + "[0&!2] 0\n", + "[0&2] 1\n", + "[!0&!2] 5\n", + "[!0&2] 6\n", + "State: 4 {1 2}\n", + "[0&!1&!2] 0\n", + "[0&!1&2] 1\n", + "[!0&!2] 5\n", + "[!0&2] 6\n", + "[0&1&!2] 7\n", + "[0&1&2] 8\n", + "State: 5 {1 2}\n", + "[0&!1&!2] 0\n", + "[!0&!2] 5\n", + "[2] 6\n", + "[0&1&!2] 7\n", + "State: 6 {1 2}\n", + "[t] 6\n", + "State: 7 {3}\n", + "[0&!1&!2] 0\n", + "[0&!1&2] 1\n", + "[!0&!2] 5\n", + "[!0&2] 6\n", + "[0&1&!2] 7\n", + "[0&1&2] 8\n", + "State: 8 {3}\n", + "[0&!1] 1\n", + "[!0] 6\n", + "[0&1] 8\n", + "--END--\n", + "\"\"\")\n", + "aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's decompose it into three strengths:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "terminal\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "cluster_5\n", + "\n", + "\n", + "cluster_6\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "8->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "8->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "1->7\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "2->7\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "2->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca450> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strictly weak\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca360> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strong\n", + "(Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bcac30> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's')):\n", + " a = spot.decompose_scc(aut, opt)\n", + " a.set_name(name)\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note how the two weak automata (i.e., stricly weak and terminal) are now using a Büchi acceptance condition (because that is sufficient for weak automata) while the strong automaton inherited the original acceptance condition.\n", + "\n", + "When extracting multiple strengths and one of the strength is **strong**, we preserve the original acceptance. For instance extracting **strong** and **inherently terminal** gives the following automaton, where only **stricly inherently weak** SCCs have become rejecting." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "cluster_5\n", + "\n", + "\n", + "cluster_6\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "8->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "8->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "1->7\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "2->7\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "2->8\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc5466300> >" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(aut, \"st\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The weak automata seem to be good candidates for further simplification. Let's add a call to `postprocess()` to out decomposition loop, trying to preserve the determinism and state-based acceptance of the original automaton." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "inherently terminal\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bcac90> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strictly inherently weak\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca270> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strong\n", + "(Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca120> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", + " a = spot.decompose_scc(aut, opt).postprocess('deterministic', 'SBAcc')\n", + " a.set_name(name)\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Streett\n", + "\n", + "Since this notebook also serves as a test suite, let's try a Streett automaton. This one was generated with\n", + "\n", + " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --automata=streett --ltl2nba=spin:ltl2tgba@-Ds' -H | \n", + " autfilt -H --merge-transitions" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))\n", + "[Streett 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "\n", + "I->7\n", + "\n", + "\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "7->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "7->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->7\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->7\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec2d0> >" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.automaton(\"\"\"\n", + "HOA: v1\n", + "States: 8\n", + "Start: 7\n", + "AP: 3 \"a\" \"b\" \"c\"\n", + "acc-name: Streett 2\n", + "Acceptance: 4 (Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n", + "properties: trans-labels explicit-labels state-acc complete\n", + "properties: deterministic\n", + "--BODY--\n", + "State: 0 {2}\n", + "[0&1] 0\n", + "[0&!1] 3\n", + "[!0] 4\n", + "State: 1 {2}\n", + "[0&1&2] 0\n", + "[0&1&!2] 1\n", + "[0&!1&!2] 2\n", + "[0&!1&2] 3\n", + "[!0&2] 4\n", + "[!0&!2] 7\n", + "State: 2 {2}\n", + "[0&1&!2] 1\n", + "[0&!1&!2] 2\n", + "[0&2] 3\n", + "[!0&2] 4\n", + "[!0&!2] 7\n", + "State: 3 {0 3}\n", + "[0] 3\n", + "[!0] 4\n", + "State: 4 {1 3}\n", + "[t] 4\n", + "State: 5 {3}\n", + "[0&!1] 3\n", + "[!0] 4\n", + "[0&1] 5\n", + "State: 6 {3}\n", + "[0&!1&!2] 2\n", + "[0&!1&2] 3\n", + "[!0&2] 4\n", + "[0&1&2] 5\n", + "[0&1&!2] 6\n", + "[!0&!2] 7\n", + "State: 7 {3}\n", + "[0&!1&!2] 2\n", + "[2] 4\n", + "[0&1&!2] 6\n", + "[!0&!2] 7\n", + "--END--\n", + "\"\"\")\n", + "aut" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "inherently terminal\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "\n", + "7->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "1->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "6->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bcac30> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strictly inherently weak\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca330> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strong\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))\n", + "[Streett 2]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca120> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", + " a = spot.decompose_strength(aut, opt)\n", + " a.set_name(name)\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The subtlety of Streett acceptance is that if a path that does not visit any accepting set infinitely often *is* accepting. So when disabling SCCs, we must be careful to label them with a combination of rejecting acceptance sets.\n", + "\n", + "This is easy to understand using an example. In the following extraction of the **strong** and **inherently terminal** parts, the rejecting SCCs (that were either rejecting or strictly inherently weak originally) have been labeled by the same acceptance sets, to ensure that they are rejected." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))\n", + "[Streett 2]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "\n", + "7->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "\n", + "1->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "6->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "6->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a & b & c\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec540> >" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(aut, 'st')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Corner cases\n", + "\n", + "When the acceptance condition is always satisfiable, all non-trivial SCCs are accepting, and inherently weak.\n", + "\n", + "This include acceptances like `Acceptance: 0 t`, but also trickier ones like `Acceptance: 1 Inf(0) | Fin(0)` that you can make as complex as you fancy.\n", + "\n", + "### `Acceptance: 0 t`\n", + "\n", + "This occur frequently whant translating LTL formulas that are safety properties:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "t\n", + "[all]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca270> >" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('(Gb|c) R a', 'any'); aut" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# There is no strong part for this automaton\n", + "assert spot.decompose_scc(aut, 's') is None" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bcac30> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bcac30> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for opt in ('w', 't'):\n", + " display(spot.decompose_scc(aut, opt))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we try to extract multiple strengths and include the (empty) strong part, this request will simply be ignored:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec870> >" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(aut, 'st')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the above is exactly the output of `decompose_strength(aut, 't')`. The `'s'` flag was actively ignored. If `'s'` had not been ignored an the automaton processed as if its strong part had to be preserved, the original acceptance conditions would have been used, and this would have prevented the disabling of the initial SCC." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `Acceptance: 1 Inf(0) | Fin(0)`\n", + "\n", + "This acceptance could be replaced by `Acceptance: 0 t` without altering the language of the automaton. However its use of acceptance sets allows us to define some automata with SCCs that are *inherently weak* but not *weak*." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec270> >" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.automaton(\"\"\"\n", + "HOA: v1\n", + "States: 4\n", + "Start: 0\n", + "AP: 1 \"a\"\n", + "Acceptance: 1 Inf(0) | Fin(0)\n", + "--BODY--\n", + "State: 0\n", + "[0] 0 \n", + "[!0] 1\n", + "State: 1\n", + "[0] 1 \n", + "[!0] 2 {0}\n", + "State: 2\n", + "[0] 1\n", + "[!0] 3\n", + "State: 3\n", + "[t] 3 {0}\n", + "--END--\n", + "\"\"\")\n", + "aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By our definitions, SCC $\\{0\\}$ and $\\{1,2\\}$ are inherently weak, and SCC $\\{3\\}$ is terminal." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "terminal\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bca2d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "strictly weak\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec630> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "no output for strong\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "all strengths\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec930> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's'), ('all strengths', 'swt')):\n", + " a = spot.decompose_scc(aut, opt)\n", + " if a:\n", + " a.set_name(name)\n", + " display(a)\n", + " else:\n", + " print(\"no output for \" + name)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# `decompose_scc()` by SCC number\n", + "\n", + "Decompose SCC can also be called by SCC numbers.\n", + "The example below show the different SCC numbers and the state they contains, before extracting the sub-automaton containing SCC 1 and 2 (i.e., anything leading to states 1 and 4 of the original automaton). This example also shows that when an `scc_info` is available for to automaton to decompose, it can be passed to `decompose_scc()` in lieu of the automaton: doing so is faster because `decompose_scc()` does not need to rebuild this object. " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SCC #0 containts states [1]\n", + "SCC #1 containts states [2]\n", + "SCC #2 containts states [4]\n", + "SCC #3 containts states [0, 3]\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4b87210> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b & !c\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec7b0> >" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('(Ga -> Gb) W c')\n", + "si = spot.scc_info(aut)\n", + "for scc in range(si.scc_count()):\n", + " print(\"SCC #{} containts states {}\".format(scc, list(si.states_of(scc))))\n", + "display(aut)\n", + "spot.decompose_scc(si, '1,2')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If an SCC number N is prefixed by `a`, it signifies that we want to extract the Nth *accepting* SCC. In the above example SCC 2 is rejecting so SCC `a2` denotes SCC 3." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "cluster_0\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7effc4bec180> >" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.decompose_scc(si, 'a2')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,5400 +5466,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": true, - "input": [ - "from IPython.display import display\n", - "import spot\n", - "spot.setup(show_default='.bans')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook demonstrates how to use the `decompose_scc()` function to split an automaton in up to three automata capturing different behaviors. This is based on the paper [Strength-based decomposition of the property B\u00fcchi automaton for faster model checking](https://www.lrde.epita.fr/~adl/dl/adl/renault.13.tacas.pdf) (TACAS'13).\n", - "\n", - "This page uses the Python bindings, but the same decompositions can be performed from the shell using [`autfilt`](https://spot.lrde.epita.fr/autfilt.html) and its `--decompose-scc` option.\n", - "\n", - "# Basics\n", - "\n", - "Let's define the following strengths of accepting SCCs:\n", - "\n", - "- an accepting SCC is **inherently weak** if it does not contain any rejecting cycle\n", - "- an accepting SCC is **inherently terminal** if it is *inherently weak* and complete (i.e. from any state, you can stay in the SCC by reading any word)\n", - "- an accepting SCC is **strictly inherently weak** if it is *inherently weak* and not complete (in other words: *weak* but not *terminal*)\n", - "- an accepting SCC is **strong** if it is not inherently weak.\n", - "\n", - "The strengths **strong**, **stricly inherently weak**, and **inherently terminal** define a partition of all accepting SCCs. The following B\u00fcchi automaton has 4 SCCs, and its 3 accepting SCCs show an example of each strength.\n", - "\n", - "Note: the reason we use the word *inherently* is that the *weak* and *terminal* properties are usually defined syntactically: an accepting SCC would be weak if all its transitions belong to the same acceptance sets. This syntactic criterion is a sufficient condition for an accepting SCC to not have any rejecting cycle, but it is not necessary. Hence a *weak* SCC is *inherently weak*; but while an *inherently weak* SCC is not necessarily *weak*, it can be modified to be *weak* without alterning the langage." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('(Ga -> Gb) W c')\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc5466510> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `decompose_strength()` function takes an automaton, and a string specifying which strength to preserve. \n", - "\n", - "The letters used for this specification are as follows:\n", - "\n", - "- `t`: (inherently) terminal\n", - "- `w`: (strictly inherently) weak\n", - "- `s`: strong\n", - "\n", - "For instance if we want to preserve only the **strictly inherently weak** part of this automaton, we should get only the SCC with the self-loop on $b$, and the SCC above it so that we can reach it. However the SCC above is not stricly weak, so it should not accept any word in the new automaton." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(aut, 'w')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca420> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can extract all the behaviors captured by the **inherently terminal** part of the automaton:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(aut, 't')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca1b0> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here is the **strong** part:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "strong = spot.decompose_scc(aut, 's'); strong" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc5466330> >" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The union of these three automata recognize the same language as the original automaton.\n", - "\n", - "\n", - "The application proposed in the aforementioned TACAS'13 paper is for parallelizing model checking. Instead of testing the emptiness of the product between `aut` and a system, one could test the emptiness **3** products in parallel: each with a sub-automaton of different strength. Model checking using weak and terminal automata can be done with much more simpler emptiness check procedures than needed for the general case. So in effect, we have isolated the \"hard\" (i.e. strong) part of the original automaton in a smaller automaton, and we only need to use a full-fledged emptiness check for this case.\n", - "\n", - "An additional bonus is that it is possible that the simplification algorithms will do a better job at simplifying the sub-automata than at simplifying the original `aut`. For instance here the `strong` automaton can be further simplified:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "strong.postprocess('small')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca180> >" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Multi-strength extraction\n", - "\n", - "The string passed to `decompose_strength()` can include multiple letters to extract multiple strengths at once." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for opt in ('sw', 'st', 'wt'):\n", - " a = spot.decompose_scc(aut, opt)\n", - " a.set_name(\"option: \" + opt)\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "option: sw\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca360> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "option: st\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca120> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "option: wt\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca390> >" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Generalized acceptance\n", - "\n", - "There is nothing that prevents the above decomposition to work with other types of acceptance.\n", - "\n", - "## Rabin\n", - "\n", - "The following Rabin automaton was generated with\n", - "\n", - " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --ltl2nba=spin:ltl2tgba@-Ds' -H | autfilt -H --merge-transitions\n", - " \n", - "(The `autfilt -H --merge-transitions` pass is just here to reduce the size of the file and make the automaton more readable.)" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton(\"\"\"\n", - "HOA: v1\n", - "States: 9\n", - "Start: 2\n", - "AP: 3 \"a\" \"b\" \"c\"\n", - "acc-name: Rabin 2\n", - "Acceptance: 4 (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))\n", - "properties: trans-labels explicit-labels state-acc complete\n", - "properties: deterministic\n", - "--BODY--\n", - "State: 0 {2}\n", - "[0&!2] 0\n", - "[0&2] 1\n", - "[!0&!2] 5\n", - "[!0&2] 6\n", - "State: 1 {2}\n", - "[0] 1\n", - "[!0] 6\n", - "State: 2 {2}\n", - "[0&!1&!2] 3\n", - "[0&1&!2] 4\n", - "[!0&!2] 5\n", - "[2] 6\n", - "State: 3 {1 2}\n", - "[0&!2] 0\n", - "[0&2] 1\n", - "[!0&!2] 5\n", - "[!0&2] 6\n", - "State: 4 {1 2}\n", - "[0&!1&!2] 0\n", - "[0&!1&2] 1\n", - "[!0&!2] 5\n", - "[!0&2] 6\n", - "[0&1&!2] 7\n", - "[0&1&2] 8\n", - "State: 5 {1 2}\n", - "[0&!1&!2] 0\n", - "[!0&!2] 5\n", - "[2] 6\n", - "[0&1&!2] 7\n", - "State: 6 {1 2}\n", - "[t] 6\n", - "State: 7 {3}\n", - "[0&!1&!2] 0\n", - "[0&!1&2] 1\n", - "[!0&!2] 5\n", - "[!0&2] 6\n", - "[0&1&!2] 7\n", - "[0&1&2] 8\n", - "State: 8 {3}\n", - "[0&!1] 1\n", - "[!0] 6\n", - "[0&1] 8\n", - "--END--\n", - "\"\"\")\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")) | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2778\n", - "))\n", - "[Rabin 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "cluster_5\n", - "\n", - "\n", - "cluster_6\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u2777\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "1->6\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\u2778\n", - "\n", - "\n", - "8->6\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "8->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2777\n", - "\n", - "\n", - "0->6\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "0->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "5->0\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\u2778\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "7->6\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "7->1\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "7->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "7->0\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "7->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec1e0> >" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's decompose it into three strengths:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's')):\n", - " a = spot.decompose_scc(aut, opt)\n", - " a.set_name(name)\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "terminal\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "cluster_5\n", - "\n", - "\n", - "cluster_6\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u24ff\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\n", - "\n", - "8->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "8->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "1->7\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "2->7\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "2->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca450> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strictly weak\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u24ff\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca360> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strong\n", - "(Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")) | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2778\n", - "))\n", - "[Rabin 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2778\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bcac30> >" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note how the two weak automata (i.e., stricly weak and terminal) are now using a B\u00fcchi acceptance condition (because that is sufficient for weak automata) while the strong automaton inherited the original acceptance condition.\n", - "\n", - "When extracting multiple strengths and one of the strength is **strong**, we preserve the original acceptance. For instance extracting **strong** and **inherently terminal** gives the following automaton, where only **stricly inherently weak** SCCs have become rejecting." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(aut, \"st\")" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")) | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2778\n", - "))\n", - "[Rabin 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "cluster_5\n", - "\n", - "\n", - "cluster_6\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\n", - "\n", - "8->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "8->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2777\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u2778\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "1->7\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "2->7\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "2->8\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc5466300> >" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The weak automata seem to be good candidates for further simplification. Let's add a call to `postprocess()` to out decomposition loop, trying to preserve the determinism and state-based acceptance of the original automaton." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", - " a = spot.decompose_scc(aut, opt).postprocess('deterministic', 'SBAcc')\n", - " a.set_name(name)\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "inherently terminal\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bcac90> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strictly inherently weak\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca270> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strong\n", - "(Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")) | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2778\n", - "))\n", - "[Rabin 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2778\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca120> >" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Streett\n", - "\n", - "Since this notebook also serves as a test suite, let's try a Streett automaton. This one was generated with\n", - "\n", - " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --automata=streett --ltl2nba=spin:ltl2tgba@-Ds' -H | \n", - " autfilt -H --merge-transitions" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton(\"\"\"\n", - "HOA: v1\n", - "States: 8\n", - "Start: 7\n", - "AP: 3 \"a\" \"b\" \"c\"\n", - "acc-name: Streett 2\n", - "Acceptance: 4 (Fin(0) | Inf(1)) & (Fin(2) | Inf(3))\n", - "properties: trans-labels explicit-labels state-acc complete\n", - "properties: deterministic\n", - "--BODY--\n", - "State: 0 {2}\n", - "[0&1] 0\n", - "[0&!1] 3\n", - "[!0] 4\n", - "State: 1 {2}\n", - "[0&1&2] 0\n", - "[0&1&!2] 1\n", - "[0&!1&!2] 2\n", - "[0&!1&2] 3\n", - "[!0&2] 4\n", - "[!0&!2] 7\n", - "State: 2 {2}\n", - "[0&1&!2] 1\n", - "[0&!1&!2] 2\n", - "[0&2] 3\n", - "[!0&2] 4\n", - "[!0&!2] 7\n", - "State: 3 {0 3}\n", - "[0] 3\n", - "[!0] 4\n", - "State: 4 {1 3}\n", - "[t] 4\n", - "State: 5 {3}\n", - "[0&!1] 3\n", - "[!0] 4\n", - "[0&1] 5\n", - "State: 6 {3}\n", - "[0&!1&!2] 2\n", - "[0&!1&2] 3\n", - "[!0&2] 4\n", - "[0&1&2] 5\n", - "[0&1&!2] 6\n", - "[!0&!2] 7\n", - "State: 7 {3}\n", - "[0&!1&!2] 2\n", - "[2] 4\n", - "[0&1&!2] 6\n", - "[!0&!2] 7\n", - "--END--\n", - "\"\"\")\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2778\n", - "))\n", - "[Streett 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\u2778\n", - "\n", - "\n", - "I->7\n", - "\n", - "\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u2777\n", - "\n", - "\n", - "7->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u2778\n", - "\n", - "\n", - "7->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2777\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2778\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->7\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->7\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "6->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec2d0> >" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", - " a = spot.decompose_strength(aut, opt)\n", - " a.set_name(name)\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "inherently terminal\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2777\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u24ff\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2777\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\u2777\n", - "\n", - "\n", - "7->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2777\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u2777\n", - "\n", - "\n", - "1->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "6->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bcac30> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strictly inherently weak\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2777\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u2777\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca330> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strong\n", - "(Fin(\n", - "\u24ff\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2778\n", - "))\n", - "[Streett 2]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2778\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u2778\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2777\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca120> >" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The subtlety of Streett acceptance is that if a path that does not visit any accepting set infinitely often *is* accepting. So when disabling SCCs, we must be careful to label them with a combination of rejecting acceptance sets.\n", - "\n", - "This is easy to understand using an example. In the following extraction of the **strong** and **inherently terminal** parts, the rejecting SCCs (that were either rejecting or strictly inherently weak originally) have been labeled by the same acceptance sets, to ensure that they are rejected." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(aut, 'st')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2778\n", - "))\n", - "[Streett 2]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u2778\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u2777\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2778\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\u2777\n", - "\n", - "\n", - "7->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\u2777\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\u2777\n", - "\n", - "\n", - "1->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "6->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "6->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "6->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a & b & c\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec540> >" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Corner cases\n", - "\n", - "When the acceptance condition is always satisfiable, all non-trivial SCCs are accepting, and inherently weak.\n", - "\n", - "This include acceptances like `Acceptance: 0 t`, but also trickier ones like `Acceptance: 1 Inf(0) | Fin(0)` that you can make as complex as you fancy.\n", - "\n", - "### `Acceptance: 0 t`\n", - "\n", - "This occur frequently whant translating LTL formulas that are safety properties:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('(Gb|c) R a', 'any'); aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "t\n", - "[all]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca270> >" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# There is no strong part for this automaton\n", - "assert spot.decompose_scc(aut, 's') is None" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 16 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for opt in ('w', 't'):\n", - " display(spot.decompose_scc(aut, opt))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bcac30> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bcac30> >" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we try to extract multiple strengths and include the (empty) strong part, this request will simply be ignored:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(aut, 'st')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec870> >" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the above is exactly the output of `decompose_strength(aut, 't')`. The `'s'` flag was actively ignored. If `'s'` had not been ignored an the automaton processed as if its strong part had to be preserved, the original acceptance conditions would have been used, and this would have prevented the disabling of the initial SCC." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### `Acceptance: 1 Inf(0) | Fin(0)`\n", - "\n", - "This acceptance could be replaced by `Acceptance: 0 t` without altering the language of the automaton. However its use of acceptance sets allows us to define some automata with SCCs that are *inherently weak* but not *weak*." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton(\"\"\"\n", - "HOA: v1\n", - "States: 4\n", - "Start: 0\n", - "AP: 1 \"a\"\n", - "Acceptance: 1 Inf(0) | Fin(0)\n", - "--BODY--\n", - "State: 0\n", - "[0] 0 \n", - "[!0] 1\n", - "State: 1\n", - "[0] 1 \n", - "[!0] 2 {0}\n", - "State: 2\n", - "[0] 1\n", - "[!0] 3\n", - "State: 3\n", - "[t] 3 {0}\n", - "--END--\n", - "\"\"\")\n", - "aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 19, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | Fin(\n", - "\u24ff\n", - ")\n", - "[Streett-like 1]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec270> >" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By our definitions, SCC $\\{0\\}$ and $\\{1,2\\}$ are inherently weak, and SCC $\\{3\\}$ is terminal." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's'), ('all strengths', 'swt')):\n", - " a = spot.decompose_scc(aut, opt)\n", - " if a:\n", - " a.set_name(name)\n", - " display(a)\n", - " else:\n", - " print(\"no output for \" + name)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "terminal\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bca2d0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "strictly weak\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec630> >" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "no output for strong\n" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "all strengths\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec930> >" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "# `decompose_scc()` by SCC number\n", - "\n", - "Decompose SCC can also be called by SCC numbers.\n", - "The example below show the different SCC numbers and the state they contains, before extracting the sub-automaton containing SCC 1 and 2 (i.e., anything leading to states 1 and 4 of the original automaton). This example also shows that when an `scc_info` is available for to automaton to decompose, it can be passed to `decompose_scc()` in lieu of the automaton: doing so is faster because `decompose_scc()` does not need to rebuild this object. " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('(Ga -> Gb) W c')\n", - "si = spot.scc_info(aut)\n", - "for scc in range(si.scc_count()):\n", - " print(\"SCC #{} containts states {}\".format(scc, list(si.states_of(scc))))\n", - "display(aut)\n", - "spot.decompose_scc(si, '1,2')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "SCC #0 containts states [1]\n", - "SCC #1 containts states [2]\n", - "SCC #2 containts states [4]\n", - "SCC #3 containts states [0, 3]\n" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a & c\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4b87210> >" - ] - }, - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 21, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b & !c\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec7b0> >" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If an SCC number N is prefixed by `a`, it signifies that we want to extract the Nth *accepting* SCC. In the above example SCC 2 is rejecting so SCC `a2` denotes SCC 3." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.decompose_scc(si, 'a2')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 22, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "cluster_0\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !c\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7effc4bec180> >" - ] - } - ], - "prompt_number": 22 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/formulas.ipynb b/tests/python/formulas.ipynb index 4786cfd19..4f20ffc1f 100644 --- a/tests/python/formulas.ipynb +++ b/tests/python/formulas.ipynb @@ -1,4 +1,887 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Handling LTL and PSL formulas\n", + "=============================" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For interactive use, formulas can be entered as text strings and passed to the `spot.formula` constructor." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{R}} (p_{3} \\land \\lnot p_{4}))$" + ], + "text/plain": [ + "p1 U (p2 R (p3 & !p4))" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('p1 U p2 R (p3 & !p4)')\n", + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\{a \\mathbin{\\mathsf{;}} b^{\\star} \\mathbin{\\mathsf{;}} c^+\\}\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt\\hbox{$\\mathord{\\rightarrow}$}} \\mathsf{G} \\mathsf{F} b$" + ], + "text/plain": [ + "{a;b[*];c[+]}<>-> GFb" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g = spot.formula('{a;b*;c[+]}<>->GFb'); g" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default the parser recognizes an infix syntax, but when this fails, it tries to read the formula with the [LBT](http://www.tcs.hut.fi/Software/maria/tools/lbt/) syntax:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$c \\land (a \\lor b)$" + ], + "text/plain": [ + "c & (a | b)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "h = spot.formula('& | a b c'); h" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Passing a `formula` to `spot.formula` simply returns the formula." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$c \\land (a \\lor b)$" + ], + "text/plain": [ + "c & (a | b)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.formula(h)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, a formula object is presented using mathjax as above.\n", + "When a formula is converted to string you get Spot's syntax by default:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'p1 U (p2 R (p3 & !p4))'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "str(f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you prefer to print the string in another syntax, you may use the `to_str()` method, with an argument that indicates the output format to use. The `latex` format assumes that you will the define macros such as `\\U`, `\\R` to render all operators as you wish. On the otherhand, the `sclatex` (with `sc` for self-contained) format hard-codes the rendering of each of those operators: this is typically the output that is used to render formulas using MathJax in a notebook. " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "spot p1 U (p2 R (p3 & !p4))\n", + "spin p1 U (p2 V (p3 && !p4))\n", + "lbt U p1 V p2 & p3 ! p4\n", + "wring (p1=1) U ((p2=1) R ((p3=1) * (p4=0)))\n", + "utf8 p1 U (p2 R (p3∧¬p4))\n", + "latex p_{1} \\U (p_{2} \\R (p_{3} \\land \\lnot p_{4}))\n", + "sclatex p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{R}} (p_{3} \\land \\lnot p_{4}))\n" + ] + } + ], + "source": [ + "for i in ['spot', 'spin', 'lbt', 'wring', 'utf8', 'latex', 'sclatex']:\n", + " print(\"%-10s%s\" % (i, f.to_str(i)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Formulas output via `format()` can also use some convenient shorthand to select the syntax:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Spin: p1 U (p2 V (p3 && !p4))\n", + "Spin+parentheses: (p1) U ((p2) V ((p3) && (!(p4))))\n", + "Spot (default): p1 U (p2 R (p3 & !p4))\n", + "Spot+shell quotes: 'p1 U (p2 R (p3 & !p4))'\n", + "LBT, right aligned: ~~~~~~~~~~~~~~~~~~~~~U p1 V p2 & p3 ! p4\n", + "LBT, no M/W/R: U p1 U & p3 ! p4 | & & p2 p3 ! p4 G & p3 ! p4\n" + ] + } + ], + "source": [ + "print(\"\"\"\\\n", + "Spin: {0:s}\n", + "Spin+parentheses: {0:sp}\n", + "Spot (default): {0}\n", + "Spot+shell quotes: {0:q}\n", + "LBT, right aligned: {0:l:~>40}\n", + "LBT, no M/W/R: {0:[MWR]l}\"\"\".format(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The specifiers that can be used with `format` are documented as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function __format__ in module spot:\n", + "\n", + "__format__(self, spec)\n", + " Format the formula according to `spec`.\n", + " \n", + " Parameters\n", + " ----------\n", + " spec : str, optional\n", + " a list of letters that specify how the formula\n", + " should be formatted.\n", + " \n", + " Supported specifiers\n", + " --------------------\n", + " \n", + " - 'f': use Spot's syntax (default)\n", + " - '8': use Spot's syntax in UTF-8 mode\n", + " - 's': use Spin's syntax\n", + " - 'l': use LBT's syntax\n", + " - 'w': use Wring's syntax\n", + " - 'x': use LaTeX output\n", + " - 'X': use self-contained LaTeX output\n", + " \n", + " Add some of those letters for additional options:\n", + " \n", + " - 'p': use full parentheses\n", + " - 'c': escape the formula for CSV output (this will\n", + " enclose the formula in double quotes, and escape\n", + " any included double quotes)\n", + " - 'h': escape the formula for HTML output\n", + " - 'd': escape double quotes and backslash,\n", + " for use in C-strings (the outermost double\n", + " quotes are *not* added)\n", + " - 'q': quote and escape for shell output, using single\n", + " quotes or double quotes depending on the contents.\n", + " - '[...]': rewrite away all the operators specified in brackets,\n", + " using spot.unabbreviate().\n", + " \n", + " - ':spec': pass the remaining specification to the\n", + " formating function for strings.\n", + "\n" + ] + } + ], + "source": [ + "help(spot.formula.__format__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A `spot.formula` object has a number of built-in predicates whose value have been computed when the formula was constructed. For instance you can check whether a formula is in negative normal form using `is_in_nenoform()`, and you can make sure it is an LTL formula (i.e. not a PSL formula) using `is_ltl_formula()`:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.is_in_nenoform() and f.is_ltl_formula()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g.is_ltl_formula()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, `is_syntactic_stutter_invariant()` tells wether the structure of the formula guarranties it to be stutter invariant. For LTL formula, this means the `X` operator should not be used. For PSL formula, this function capture all formulas built using the [siPSL grammar](http://www.daxc.de/eth/paper/09atva.pdf)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.is_syntactic_stutter_invariant()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.formula('{a[*];b}<>->c').is_syntactic_stutter_invariant()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.formula('{a[+];b[*]}<>->d').is_syntactic_stutter_invariant()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`spot.relabel` renames the atomic propositions that occur in a formula, using either letters, or numbered propositions:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$``\\mathit{a > b}\\textrm{''} \\land ``\\mathit{proc[2]@init}\\textrm{''} \\land \\mathsf{G} \\mathsf{F} \\mathit{\\_foo\\_}$" + ], + "text/plain": [ + "\"a > b\" & \"proc[2]@init\" & GF_foo_" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gf = spot.formula('(GF_foo_) && \"a > b\" && \"proc[2]@init\"'); gf" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$a \\land b \\land \\mathsf{G} \\mathsf{F} c$" + ], + "text/plain": [ + "a & b & GFc" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.relabel(gf, spot.Abc)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$p_{0} \\land p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2}$" + ], + "text/plain": [ + "p0 & p1 & GFp2" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.relabel(gf, spot.Pnn)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The AST of any formula can be displayed with `show_ast()`. Despite the name, this is not a tree but a DAG, because identical subtrees are merged. Binary operators have their left and right operands denoted with `L` and `R`, while non-commutative n-ary operators have their operands numbered." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{a;b[*];c[+]}<>-> GFb\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "0\n", + "\n", + "EConcat\n", + "\n", + "\n", + "1\n", + "\n", + "Concat\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "L\n", + "\n", + "\n", + "7\n", + "\n", + "G\n", + "\n", + "\n", + "0->7\n", + "\n", + "\n", + "R\n", + "\n", + "\n", + "2\n", + "\n", + "a\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "Star\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "5\n", + "\n", + "Star\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "4\n", + "\n", + "b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "c\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "F\n", + "\n", + "\n", + "7->8\n", + "\n", + "\n", + "\n", + "\n", + "8->4\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(g); g.show_ast()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Any formula can also be classified in the temporal hierarchy of Manna & Pnueli" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "Reactivity\n", + "Recurrence\n", + "Persistence\n", + "Obligation\n", + "Safety\n", + "Guarantee\n", + "\n", + "\n", + "Monitor\n", + "Deterministic Büchi\n", + "Terminal Büchi\n", + "Weak Büchi\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g.show_mp_hierarchy()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'recurrence'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.mp_class(g, 'v')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{F} (a \\land \\mathsf{X} (\\lnot a \\land b))$" + ], + "text/plain": [ + "F(a & X(!a & b))" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('F(a & X(!a & b))'); f" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Etessami's rule for removing X (valid only in stutter-invariant formulas)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{F} (a \\land ((a \\land (a \\mathbin{\\mathsf{U}} (\\lnot a \\land b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} \\lnot a) \\lor (b \\mathbin{\\mathsf{U}} \\lnot a))) \\lor (\\lnot a \\land (\\lnot a \\mathbin{\\mathsf{U}} (a \\land \\lnot a \\land b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} a) \\lor (b \\mathbin{\\mathsf{U}} a))) \\lor (b \\land (b \\mathbin{\\mathsf{U}} (\\lnot a \\land b \\land \\lnot b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} \\lnot b) \\lor (a \\mathbin{\\mathsf{U}} \\lnot b))) \\lor (\\lnot b \\land (\\lnot b \\mathbin{\\mathsf{U}} (\\lnot a \\land b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} b) \\lor (a \\mathbin{\\mathsf{U}} b))) \\lor (\\lnot a \\land b \\land (\\mathsf{G} \\lnot a \\lor \\mathsf{G} a) \\land (\\mathsf{G} \\lnot b \\lor \\mathsf{G} b))))$" + ], + "text/plain": [ + "F(a & ((a & (a U (!a & b)) & ((!b U !a) | (b U !a))) | (!a & (!a U (a & !a & b)) & ((!b U a) | (b U a))) | (b & (b U (!a & b & !b)) & ((!a U !b) | (a U !b))) | (!b & (!b U (!a & b)) & ((!a U b) | (a U b))) | (!a & b & (G!a | Ga) & (G!b | Gb))))" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_x(f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Removing abbreviated operators" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$(\\bot \\mathbin{\\mathsf{R}} \\lnot (a \\leftrightarrow b)) \\rightarrow (\\top \\mathbin{\\mathsf{U}} (a \\leftrightarrow b))$" + ], + "text/plain": [ + "(0 R !(a <-> b)) -> (1 U (a <-> b))" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula(\"G(a xor b) -> F(a <-> b)\")\n", + "spot.unabbreviate(f, \"GF^\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$(\\top \\mathbin{\\mathsf{U}} ((a \\land b) \\lor (\\lnot a \\land \\lnot b))) \\lor \\lnot (\\bot \\mathbin{\\mathsf{R}} ((\\lnot a \\land b) \\lor (a \\land \\lnot b)))$" + ], + "text/plain": [ + "(1 U ((a & b) | (!a & !b))) | !(0 R ((!a & b) | (a & !b)))" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.unabbreviate(f, \"GF^ei\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Nesting level of operators" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "U 3\n", + "F 2\n", + "U 3\n", + "F 2\n", + "FU 4\n" + ] + } + ], + "source": [ + "f = spot.formula('F(b & X(a U b U ((a W Fb) | (c U d))))')\n", + "print(\"U\", spot.nesting_depth(f, spot.op_U))\n", + "print(\"F\", spot.nesting_depth(f, spot.op_F))\n", + "# These following two are syntactic sugar for the above two\n", + "print(\"U\", spot.nesting_depth(f, \"U\"))\n", + "print(\"F\", spot.nesting_depth(f, \"F\"))\n", + "# If you want to consider \"U\" and \"F\" are a similar type of\n", + "# operator, you can count both with\n", + "print(\"FU\", spot.nesting_depth(f, \"FU\"))" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,857 +899,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Handling LTL and PSL formulas\n", - "=============================" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For interactive use, formulas can be entered as text strings and passed to the `spot.formula` constructor." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('p1 U p2 R (p3 & !p4)')\n", - "f" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{R}} (p_{3} \\land \\lnot p_{4}))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "p1 U (p2 R (p3 & !p4))" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = spot.formula('{a;b*;c[+]}<>->GFb'); g" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\{a \\mathbin{\\mathsf{;}} b^{\\star} \\mathbin{\\mathsf{;}} c^+\\}\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt\\hbox{$\\mathord{\\rightarrow}$}} \\mathsf{G} \\mathsf{F} b$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "{a;b[*];c[+]}<>-> GFb" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default the parser recognizes an infix syntax, but when this fails, it tries to read the formula with the [LBT](http://www.tcs.hut.fi/Software/maria/tools/lbt/) syntax:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "h = spot.formula('& | a b c'); h" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$c \\land (a \\lor b)$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "text": [ - "c & (a | b)" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Passing a `formula` to `spot.formula` simply returns the formula." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.formula(h)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$c \\land (a \\lor b)$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "c & (a | b)" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, a formula object is presented using mathjax as above.\n", - "When a formula is converted to string you get Spot's syntax by default:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "str(f)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "text": [ - "'p1 U (p2 R (p3 & !p4))'" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you prefer to print the string in another syntax, you may use the `to_str()` method, with an argument that indicates the output format to use. The `latex` format assumes that you will the define macros such as `\\U`, `\\R` to render all operators as you wish. On the otherhand, the `sclatex` (with `sc` for self-contained) format hard-codes the rendering of each of those operators: this is typically the output that is used to render formulas using MathJax in a notebook. " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for i in ['spot', 'spin', 'lbt', 'wring', 'utf8', 'latex', 'sclatex']:\n", - " print(\"%-10s%s\" % (i, f.to_str(i)))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "spot p1 U (p2 R (p3 & !p4))\n", - "spin p1 U (p2 V (p3 && !p4))\n", - "lbt U p1 V p2 & p3 ! p4\n", - "wring (p1=1) U ((p2=1) R ((p3=1) * (p4=0)))\n", - "utf8 p1 U (p2 R (p3\u2227\u00acp4))\n", - "latex p_{1} \\U (p_{2} \\R (p_{3} \\land \\lnot p_{4}))\n", - "sclatex p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{R}} (p_{3} \\land \\lnot p_{4}))\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Formulas output via `format()` can also use some convenient shorthand to select the syntax:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(\"\"\"\\\n", - "Spin: {0:s}\n", - "Spin+parentheses: {0:sp}\n", - "Spot (default): {0}\n", - "Spot+shell quotes: {0:q}\n", - "LBT, right aligned: {0:l:~>40}\n", - "LBT, no M/W/R: {0:[MWR]l}\"\"\".format(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Spin: p1 U (p2 V (p3 && !p4))\n", - "Spin+parentheses: (p1) U ((p2) V ((p3) && (!(p4))))\n", - "Spot (default): p1 U (p2 R (p3 & !p4))\n", - "Spot+shell quotes: 'p1 U (p2 R (p3 & !p4))'\n", - "LBT, right aligned: ~~~~~~~~~~~~~~~~~~~~~U p1 V p2 & p3 ! p4\n", - "LBT, no M/W/R: U p1 U & p3 ! p4 | & & p2 p3 ! p4 G & p3 ! p4\n" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The specifiers that can be used with `format` are documented as follows:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "help(spot.formula.__format__)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Help on function __format__ in module spot:\n", - "\n", - "__format__(self, spec)\n", - " Format the formula according to `spec`.\n", - " \n", - " Parameters\n", - " ----------\n", - " spec : str, optional\n", - " a list of letters that specify how the formula\n", - " should be formatted.\n", - " \n", - " Supported specifiers\n", - " --------------------\n", - " \n", - " - 'f': use Spot's syntax (default)\n", - " - '8': use Spot's syntax in UTF-8 mode\n", - " - 's': use Spin's syntax\n", - " - 'l': use LBT's syntax\n", - " - 'w': use Wring's syntax\n", - " - 'x': use LaTeX output\n", - " - 'X': use self-contained LaTeX output\n", - " \n", - " Add some of those letters for additional options:\n", - " \n", - " - 'p': use full parentheses\n", - " - 'c': escape the formula for CSV output (this will\n", - " enclose the formula in double quotes, and escape\n", - " any included double quotes)\n", - " - 'h': escape the formula for HTML output\n", - " - 'd': escape double quotes and backslash,\n", - " for use in C-strings (the outermost double\n", - " quotes are *not* added)\n", - " - 'q': quote and escape for shell output, using single\n", - " quotes or double quotes depending on the contents.\n", - " - '[...]': rewrite away all the operators specified in brackets,\n", - " using spot.unabbreviate().\n", - " \n", - " - ':spec': pass the remaining specification to the\n", - " formating function for strings.\n", - "\n" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A `spot.formula` object has a number of built-in predicates whose value have been computed when the formula was constructed. For instance you can check whether a formula is in negative normal form using `is_in_nenoform()`, and you can make sure it is an LTL formula (i.e. not a PSL formula) using `is_ltl_formula()`:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.is_in_nenoform() and f.is_ltl_formula()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "text": [ - "True" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.is_ltl_formula()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "text": [ - "False" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, `is_syntactic_stutter_invariant()` tells wether the structure of the formula guarranties it to be stutter invariant. For LTL formula, this means the `X` operator should not be used. For PSL formula, this function capture all formulas built using the [siPSL grammar](http://www.daxc.de/eth/paper/09atva.pdf)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f.is_syntactic_stutter_invariant()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "text": [ - "True" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.formula('{a[*];b}<>->c').is_syntactic_stutter_invariant()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "text": [ - "False" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.formula('{a[+];b[*]}<>->d').is_syntactic_stutter_invariant()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "True" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`spot.relabel` renames the atomic propositions that occur in a formula, using either letters, or numbered propositions:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "gf = spot.formula('(GF_foo_) && \"a > b\" && \"proc[2]@init\"'); gf" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$``\\mathit{a > b}\\textrm{''} \\land ``\\mathit{proc[2]@init}\\textrm{''} \\land \\mathsf{G} \\mathsf{F} \\mathit{\\_foo\\_}$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "text": [ - "\"a > b\" & \"proc[2]@init\" & GF_foo_" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.relabel(gf, spot.Abc)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$a \\land b \\land \\mathsf{G} \\mathsf{F} c$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "text": [ - "a & b & GFc" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.relabel(gf, spot.Pnn)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$p_{0} \\land p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2}$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 17, - "text": [ - "p0 & p1 & GFp2" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The AST of any formula can be displayed with `show_ast()`. Despite the name, this is not a tree but a DAG, because identical subtrees are merged. Binary operators have their left and right operands denoted with `L` and `R`, while non-commutative n-ary operators have their operands numbered." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(g); g.show_ast()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{a;b[*];c[+]}<>-> GFb\n" - ] - }, - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "0\n", - "\n", - "EConcat\n", - "\n", - "\n", - "1\n", - "\n", - "Concat\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "L\n", - "\n", - "\n", - "7\n", - "\n", - "G\n", - "\n", - "\n", - "0->7\n", - "\n", - "\n", - "R\n", - "\n", - "\n", - "2\n", - "\n", - "a\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "Star\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "2\n", - "\n", - "\n", - "5\n", - "\n", - "Star\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "3\n", - "\n", - "\n", - "4\n", - "\n", - "b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "c\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "F\n", - "\n", - "\n", - "7->8\n", - "\n", - "\n", - "\n", - "\n", - "8->4\n", - "\n", - "\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Any formula can also be classified in the temporal hierarchy of Manna & Pnueli" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.show_mp_hierarchy()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 19, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - "\n", - "Reactivity\n", - "Recurrence\n", - "Persistence\n", - "Obligation\n", - "Safety\n", - "Guarantee\n", - "\n", - "\n", - "Monitor\n", - "Deterministic B\u00fcchi\n", - "Terminal B\u00fcchi\n", - "Weak B\u00fcchi\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.mp_class(g, 'v')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 20, - "text": [ - "'recurrence'" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('F(a & X(!a & b))'); f" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{F} (a \\land \\mathsf{X} (\\lnot a \\land b))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 21, - "text": [ - "F(a & X(!a & b))" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Etessami's rule for removing X (valid only in stutter-invariant formulas)" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_x(f)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{F} (a \\land ((a \\land (a \\mathbin{\\mathsf{U}} (\\lnot a \\land b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} \\lnot a) \\lor (b \\mathbin{\\mathsf{U}} \\lnot a))) \\lor (\\lnot a \\land (\\lnot a \\mathbin{\\mathsf{U}} (a \\land \\lnot a \\land b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} a) \\lor (b \\mathbin{\\mathsf{U}} a))) \\lor (b \\land (b \\mathbin{\\mathsf{U}} (\\lnot a \\land b \\land \\lnot b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} \\lnot b) \\lor (a \\mathbin{\\mathsf{U}} \\lnot b))) \\lor (\\lnot b \\land (\\lnot b \\mathbin{\\mathsf{U}} (\\lnot a \\land b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} b) \\lor (a \\mathbin{\\mathsf{U}} b))) \\lor (\\lnot a \\land b \\land (\\mathsf{G} \\lnot a \\lor \\mathsf{G} a) \\land (\\mathsf{G} \\lnot b \\lor \\mathsf{G} b))))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 22, - "text": [ - "F(a & ((a & (a U (!a & b)) & ((!b U !a) | (b U !a))) | (!a & (!a U (a & !a & b)) & ((!b U a) | (b U a))) | (b & (b U (!a & b & !b)) & ((!a U !b) | (a U !b))) | (!b & (!b U (!a & b)) & ((!a U b) | (a U b))) | (!a & b & (G!a | Ga) & (G!b | Gb))))" - ] - } - ], - "prompt_number": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Removing abbreviated operators" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula(\"G(a xor b) -> F(a <-> b)\")\n", - "spot.unabbreviate(f, \"GF^\")" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$(\\bot \\mathbin{\\mathsf{R}} \\lnot (a \\leftrightarrow b)) \\rightarrow (\\top \\mathbin{\\mathsf{U}} (a \\leftrightarrow b))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 23, - "text": [ - "(0 R !(a <-> b)) -> (1 U (a <-> b))" - ] - } - ], - "prompt_number": 23 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.unabbreviate(f, \"GF^ei\")" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$(\\top \\mathbin{\\mathsf{U}} ((a \\land b) \\lor (\\lnot a \\land \\lnot b))) \\lor \\lnot (\\bot \\mathbin{\\mathsf{R}} ((\\lnot a \\land b) \\lor (a \\land \\lnot b)))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 24, - "text": [ - "(1 U ((a & b) | (!a & !b))) | !(0 R ((!a & b) | (a & !b)))" - ] - } - ], - "prompt_number": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Nesting level of operators" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('F(b & X(a U b U ((a W Fb) | (c U d))))')\n", - "print(\"U\", spot.nesting_depth(f, spot.op_U))\n", - "print(\"F\", spot.nesting_depth(f, spot.op_F))\n", - "# These following two are syntactic sugar for the above two\n", - "print(\"U\", spot.nesting_depth(f, \"U\"))\n", - "print(\"F\", spot.nesting_depth(f, \"F\"))\n", - "# If you want to consider \"U\" and \"F\" are a similar type of\n", - "# operator, you can count both with\n", - "print(\"FU\", spot.nesting_depth(f, \"FU\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "U 3\n", - "F 2\n", - "U 3\n", - "F 2\n", - "FU 4\n" - ] - } - ], - "prompt_number": 25 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/gen.ipynb b/tests/python/gen.ipynb index 78af79137..b313e1bdc 100644 --- a/tests/python/gen.ipynb +++ b/tests/python/gen.ipynb @@ -1,4 +1,935 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Formulas & Automata generators\n", + "\n", + "The `spot.gen` package contains the functions used to generate the patterns produced by [`genltl`](https://spot.lrde.epita.fr/genltl.html) and [`genaut`](https://spot.lrde.epita.fr/genaut.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "import spot.gen as sg\n", + "spot.setup()\n", + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LTL patterns\n", + "\n", + "Generation of LTL formulas is done via the `ltl_pattern()` function. This takes two arguments: a pattern id, and a pattern size (or index if the id refers to a list)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{G} \\mathsf{F} p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2} \\land \\mathsf{G} \\mathsf{F} p_{3}$" + ], + "text/plain": [ + "GFp1 & GFp2 & GFp3" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sg.ltl_pattern(sg.LTL_AND_GF, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{F} (p \\land \\mathsf{X} p \\land \\mathsf{X} \\mathsf{X} p \\land \\mathsf{X} \\mathsf{X} \\mathsf{X} p) \\land \\mathsf{F} (q \\land \\mathsf{X} q \\land \\mathsf{X} \\mathsf{X} q \\land \\mathsf{X} \\mathsf{X} \\mathsf{X} q)$" + ], + "text/plain": [ + "F(p & Xp & XXp & XXXp) & F(q & Xq & XXq & XXXq)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sg.ltl_pattern(sg.LTL_CCJ_BETA_PRIME, 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To see the list of supported patterns, the easiest way is to look at the `--help` output of `genltl`. The above pattern for instance is attached to option `--ccj-beta-prime`. The name of the pattern identifier is the same using capital letters, underscores, and an `LTL_` prefix. If a pattern has multiple aliased options in `genltl`, the first one used for the identifier (e.g., `genltl` accept both `--dac-patterns` and `--spec-patterns` as synonyms to denote the patterns of `spot.gen.LTL_DAC_PATTERNS`).\n", + "\n", + "Multiple patterns can be generated using the `ltl_patterns()` function. It's arguments should be either can be:\n", + " - pairs of the form `(id, n)`: in this case the pattern `id` with size/index `n` is returned,\n", + " - triplets of the form `(id, min, max)`: in this case the patterns are output for all `n` between `min` and `max` included,\n", + " - an integer `id`: then this is equivalent to `(id, 1, 10)` if the pattern has now upper bound, or `(id, 1, upper)` if the patter `id` has an upper bound `upper`. This is mostly used when the pattern id correspond to a hard-coded list of formulas.\n", + "\n", + "Here is an example showing these three types of arguments:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$(\\mathsf{G} \\mathsf{F} p_{1} \\lor \\mathsf{F} \\mathsf{G} p_{2}) \\land (\\mathsf{G} \\mathsf{F} p_{2} \\lor \\mathsf{F} \\mathsf{G} p_{3}) \\land (\\mathsf{G} \\mathsf{F} p_{3} \\lor \\mathsf{F} \\mathsf{G} p_{4})$" + ], + "text/plain": [ + "(GFp1 | FGp2) & (GFp2 | FGp3) & (GFp3 | FGp4)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} \\mathsf{G} p_{1}$" + ], + "text/plain": [ + "FGp1" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} \\mathsf{G} p_{1} \\land \\mathsf{F} \\mathsf{G} p_{2}$" + ], + "text/plain": [ + "FGp1 & FGp2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} \\mathsf{G} p_{1} \\land \\mathsf{F} \\mathsf{G} p_{2} \\land \\mathsf{F} \\mathsf{G} p_{3}$" + ], + "text/plain": [ + "FGp1 & FGp2 & FGp3" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{G} p_{2})$" + ], + "text/plain": [ + "p0 U (p1 & Gp2)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{X} (p_{2} \\mathbin{\\mathsf{U}} p_{3}))$" + ], + "text/plain": [ + "p0 U (p1 & X(p2 U p3))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{X} (p_{2} \\land \\mathsf{F} (p_{3} \\land \\mathsf{X} \\mathsf{F} (p_{4} \\land \\mathsf{X} \\mathsf{F} (p_{5} \\land \\mathsf{X} \\mathsf{F} p_{6})))))$" + ], + "text/plain": [ + "p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)))))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} (p_{0} \\land \\mathsf{X} \\mathsf{G} p_{1})$" + ], + "text/plain": [ + "F(p0 & XGp1)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} (p_{0} \\land \\mathsf{X} (p_{1} \\land \\mathsf{X} \\mathsf{F} p_{2}))$" + ], + "text/plain": [ + "F(p0 & X(p1 & XFp2))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{F} (p_{0} \\land \\mathsf{X} (p_{1} \\mathbin{\\mathsf{U}} p_{2}))$" + ], + "text/plain": [ + "F(p0 & X(p1 U p2))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{G} \\mathsf{F} p_{0} \\lor \\mathsf{F} \\mathsf{G} p_{1}$" + ], + "text/plain": [ + "GFp0 | FGp1" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{G} (p_{0} \\rightarrow (p_{1} \\mathbin{\\mathsf{U}} p_{2}))$" + ], + "text/plain": [ + "G(p0 -> (p1 U p2))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{G} (p_{0} \\land \\mathsf{X} \\mathsf{F} (p_{1} \\land \\mathsf{X} \\mathsf{F} (p_{2} \\land \\mathsf{X} \\mathsf{F} p_{3})))$" + ], + "text/plain": [ + "G(p0 & XF(p1 & XF(p2 & XFp3)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{G} \\mathsf{F} p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2} \\land \\mathsf{G} \\mathsf{F} p_{3} \\land \\mathsf{G} \\mathsf{F} p_{0} \\land \\mathsf{G} \\mathsf{F} p_{4}$" + ], + "text/plain": [ + "GFp1 & GFp2 & GFp3 & GFp0 & GFp4" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$(p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\mathbin{\\mathsf{U}} p_{2})) \\lor (p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{U}} p_{0})) \\lor (p_{2} \\mathbin{\\mathsf{U}} (p_{0} \\mathbin{\\mathsf{U}} p_{1}))$" + ], + "text/plain": [ + "(p0 U (p1 U p2)) | (p1 U (p2 U p0)) | (p2 U (p0 U p1))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\mathsf{G} (p_{0} \\rightarrow (p_{1} \\mathbin{\\mathsf{U}} (\\mathsf{G} p_{2} \\lor \\mathsf{G} p_{3})))$" + ], + "text/plain": [ + "G(p0 -> (p1 U (Gp2 | Gp3)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for f in sg.ltl_patterns((sg.LTL_GH_R, 3), (sg.LTL_AND_FG, 1, 3), sg.LTL_EH_PATTERNS):\n", + " display(f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Automata patterns\n", + "\n", + "We currently have only a couple of generators of automata:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "0->5\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "0->6\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "(!a & b) | (a & !b)\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "(!a & !b) | (a & b)\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a | b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a | b\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "!a | b\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "6->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "!a | b\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))\n", + "[Streett 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "1->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "9\n", + "\n", + "9\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "10\n", + "\n", + "10\n", + "\n", + "\n", + "6->10\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "9->9\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "\n", + "9->8\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "7->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "10->10\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "11\n", + "\n", + "11\n", + "\n", + "\n", + "\n", + "10->11\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "8->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "11->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "1->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "2->8\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "8->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "9\n", + "\n", + "9\n", + "\n", + "\n", + "3->9\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "9->8\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "9->9\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(sg.aut_pattern(sg.AUT_KS_NCA, 3).show('.a'),\n", + " sg.aut_pattern(sg.AUT_L_DSA, 3).show('.a'),\n", + " sg.aut_pattern(sg.AUT_L_NBA, 3).show('.a'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Multiple automata can be generated using the `aut_patterns()` function, which works similarly to `ltl_patterns()`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "5\n", + "7\n", + "9\n", + "11\n", + "13\n", + "15\n", + "17\n", + "19\n", + "21\n" + ] + } + ], + "source": [ + "for aut in sg.aut_patterns(sg.AUT_KS_NCA):\n", + " print(aut.num_states())" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,904 +947,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Formulas & Automata generators\n", - "\n", - "The `spot.gen` package contains the functions used to generate the patterns produced by [`genltl`](https://spot.lrde.epita.fr/genltl.html) and [`genaut`](https://spot.lrde.epita.fr/genaut.html)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "import spot.gen as sg\n", - "spot.setup()\n", - "from IPython.display import display" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## LTL patterns\n", - "\n", - "Generation of LTL formulas is done via the `ltl_pattern()` function. This takes two arguments: a pattern id, and a pattern size (or index if the id refers to a list)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sg.ltl_pattern(sg.LTL_AND_GF, 3)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{G} \\mathsf{F} p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2} \\land \\mathsf{G} \\mathsf{F} p_{3}$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "GFp1 & GFp2 & GFp3" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sg.ltl_pattern(sg.LTL_CCJ_BETA_PRIME, 4)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{F} (p \\land \\mathsf{X} p \\land \\mathsf{X} \\mathsf{X} p \\land \\mathsf{X} \\mathsf{X} \\mathsf{X} p) \\land \\mathsf{F} (q \\land \\mathsf{X} q \\land \\mathsf{X} \\mathsf{X} q \\land \\mathsf{X} \\mathsf{X} \\mathsf{X} q)$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "F(p & Xp & XXp & XXXp) & F(q & Xq & XXq & XXXq)" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To see the list of supported patterns, the easiest way is to look at the `--help` output of `genltl`. The above pattern for instance is attached to option `--ccj-beta-prime`. The name of the pattern identifier is the same using capital letters, underscores, and an `LTL_` prefix. If a pattern has multiple aliased options in `genltl`, the first one used for the identifier (e.g., `genltl` accept both `--dac-patterns` and `--spec-patterns` as synonyms to denote the patterns of `spot.gen.LTL_DAC_PATTERNS`).\n", - "\n", - "Multiple patterns can be generated using the `ltl_patterns()` function. It's arguments should be either can be:\n", - " - pairs of the form `(id, n)`: in this case the pattern `id` with size/index `n` is returned,\n", - " - triplets of the form `(id, min, max)`: in this case the patterns are output for all `n` between `min` and `max` included,\n", - " - an integer `id`: then this is equivalent to `(id, 1, 10)` if the pattern has now upper bound, or `(id, 1, upper)` if the patter `id` has an upper bound `upper`. This is mostly used when the pattern id correspond to a hard-coded list of formulas.\n", - "\n", - "Here is an example showing these three types of arguments:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for f in sg.ltl_patterns((sg.LTL_GH_R, 3), (sg.LTL_AND_FG, 1, 3), sg.LTL_EH_PATTERNS):\n", - " display(f)" - ], - "language": "python", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "latex": [ - "$(\\mathsf{G} \\mathsf{F} p_{1} \\lor \\mathsf{F} \\mathsf{G} p_{2}) \\land (\\mathsf{G} \\mathsf{F} p_{2} \\lor \\mathsf{F} \\mathsf{G} p_{3}) \\land (\\mathsf{G} \\mathsf{F} p_{3} \\lor \\mathsf{F} \\mathsf{G} p_{4})$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "(GFp1 | FGp2) & (GFp2 | FGp3) & (GFp3 | FGp4)" - ] - }, - { - "latex": [ - "$\\mathsf{F} \\mathsf{G} p_{1}$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "FGp1" - ] - }, - { - "latex": [ - "$\\mathsf{F} \\mathsf{G} p_{1} \\land \\mathsf{F} \\mathsf{G} p_{2}$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "FGp1 & FGp2" - ] - }, - { - "latex": [ - "$\\mathsf{F} \\mathsf{G} p_{1} \\land \\mathsf{F} \\mathsf{G} p_{2} \\land \\mathsf{F} \\mathsf{G} p_{3}$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "FGp1 & FGp2 & FGp3" - ] - }, - { - "latex": [ - "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{G} p_{2})$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "p0 U (p1 & Gp2)" - ] - }, - { - "latex": [ - "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{X} (p_{2} \\mathbin{\\mathsf{U}} p_{3}))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "p0 U (p1 & X(p2 U p3))" - ] - }, - { - "latex": [ - "$p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\land \\mathsf{X} (p_{2} \\land \\mathsf{F} (p_{3} \\land \\mathsf{X} \\mathsf{F} (p_{4} \\land \\mathsf{X} \\mathsf{F} (p_{5} \\land \\mathsf{X} \\mathsf{F} p_{6})))))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)))))" - ] - }, - { - "latex": [ - "$\\mathsf{F} (p_{0} \\land \\mathsf{X} \\mathsf{G} p_{1})$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "F(p0 & XGp1)" - ] - }, - { - "latex": [ - "$\\mathsf{F} (p_{0} \\land \\mathsf{X} (p_{1} \\land \\mathsf{X} \\mathsf{F} p_{2}))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "F(p0 & X(p1 & XFp2))" - ] - }, - { - "latex": [ - "$\\mathsf{F} (p_{0} \\land \\mathsf{X} (p_{1} \\mathbin{\\mathsf{U}} p_{2}))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "F(p0 & X(p1 U p2))" - ] - }, - { - "latex": [ - "$\\mathsf{G} \\mathsf{F} p_{0} \\lor \\mathsf{F} \\mathsf{G} p_{1}$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "GFp0 | FGp1" - ] - }, - { - "latex": [ - "$\\mathsf{G} (p_{0} \\rightarrow (p_{1} \\mathbin{\\mathsf{U}} p_{2}))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "G(p0 -> (p1 U p2))" - ] - }, - { - "latex": [ - "$\\mathsf{G} (p_{0} \\land \\mathsf{X} \\mathsf{F} (p_{1} \\land \\mathsf{X} \\mathsf{F} (p_{2} \\land \\mathsf{X} \\mathsf{F} p_{3})))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "G(p0 & XF(p1 & XF(p2 & XFp3)))" - ] - }, - { - "latex": [ - "$\\mathsf{G} \\mathsf{F} p_{1} \\land \\mathsf{G} \\mathsf{F} p_{2} \\land \\mathsf{G} \\mathsf{F} p_{3} \\land \\mathsf{G} \\mathsf{F} p_{0} \\land \\mathsf{G} \\mathsf{F} p_{4}$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "GFp1 & GFp2 & GFp3 & GFp0 & GFp4" - ] - }, - { - "latex": [ - "$(p_{0} \\mathbin{\\mathsf{U}} (p_{1} \\mathbin{\\mathsf{U}} p_{2})) \\lor (p_{1} \\mathbin{\\mathsf{U}} (p_{2} \\mathbin{\\mathsf{U}} p_{0})) \\lor (p_{2} \\mathbin{\\mathsf{U}} (p_{0} \\mathbin{\\mathsf{U}} p_{1}))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "(p0 U (p1 U p2)) | (p1 U (p2 U p0)) | (p2 U (p0 U p1))" - ] - }, - { - "latex": [ - "$\\mathsf{G} (p_{0} \\rightarrow (p_{1} \\mathbin{\\mathsf{U}} (\\mathsf{G} p_{2} \\lor \\mathsf{G} p_{3})))$" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "G(p0 -> (p1 U (Gp2 | Gp3)))" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Automata patterns\n", - "\n", - "We currently have only a couple of generators of automata:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "display(sg.aut_pattern(sg.AUT_KS_NCA, 3).show('.a'),\n", - " sg.aut_pattern(sg.AUT_L_DSA, 3).show('.a'),\n", - " sg.aut_pattern(sg.AUT_L_NBA, 3).show('.a'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "0->5\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "0->6\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "(!a & b) | (a & !b)\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "(!a & !b) | (a & b)\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a | b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a | b\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "!a | b\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "6->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "!a | b\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2778\n", - ")) & (Fin(\n", - "\u2779\n", - ") | Inf(\n", - "\u277a\n", - "))\n", - "[Streett 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\u24ff\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\u2776\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "1->5\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\u2777\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "9\n", - "\n", - "9\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\u2778\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "10\n", - "\n", - "10\n", - "\n", - "\n", - "6->10\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "9->9\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\u2779\n", - "\n", - "\n", - "9->8\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "7->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "10->10\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "11\n", - "\n", - "11\n", - "\u277a\n", - "\n", - "\n", - "10->11\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "8->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "11->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "1->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7->0\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\n", - "\n", - "2->8\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "8->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "9\n", - "\n", - "9\n", - "\n", - "\n", - "3->9\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "9->8\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "9->9\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "6->3\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Multiple automata can be generated using the `aut_patterns()` function, which works similarly to `ltl_patterns()`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for aut in sg.aut_patterns(sg.AUT_KS_NCA):\n", - " print(aut.num_states())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "3\n", - "5\n", - "7\n", - "9\n", - "11\n", - "13\n", - "15\n", - "17\n", - "19\n", - "21\n" - ] - } - ], - "prompt_number": 6 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/highlighting.ipynb b/tests/python/highlighting.ipynb index 1d89b59e7..c7247503a 100644 --- a/tests/python/highlighting.ipynb +++ b/tests/python/highlighting.ipynb @@ -1,4 +1,2514 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup()\n", + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook shows you different ways in which states or transitions can be highlighted in Spot. \n", + "\n", + "It should be noted that highlighting works using some special [named properties](https://spot.lrde.epita.fr/concepts.html#named-properties): basically, two maps that are attached to the automaton, and associated state or edge numbers to color numbers. This named properties are fragile: they will be lost if the automaton is transformed into a new automaton, and they can become meaningless of the automaton is modified in place (e.g., if the transitions or states are reordered).\n", + "\n", + "Nonetheless, highlighting is OK to use right before displaying or printing the automaton. The `dot` and `hoa` printer both know how to represent highlighted states and transitions.\n", + "\n", + "# Manual highlighting" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "a = spot.translate('a U b U c')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `#` option of `print_dot()` can be used to display the internal number of each transition " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "#6\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "c\n", + "#4\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & b & !c\n", + "#5\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "#1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "c\n", + "#2\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "#3\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.show('.#')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using these numbers you can selectively hightlight some transitions. The second argument is a color number (from a list of predefined colors)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & b & !c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe1205e8990> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.highlight_edges([2, 4, 5], 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that these `highlight_` functions work for edges and states, and come with both singular (changing the color of single state or edge) and plural versions.\n", + "\n", + "They modify the automaton in place." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & b & !c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe1205e8a80> >" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.highlight_edge(6, 2).highlight_states((0, 1), 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The plural version can take a list or tuple of state numbers (as above) or of Booleans (as below). In the latter case the indices of the True values give the states to highlight." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "I->2\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & b & !c\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe1205e8990> >" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.highlight_states([False, True, True], 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Saving to HOA 1.1\n", + "\n", + "When saving to HOA format, the highlighting is only output if version 1.1 of the format is selected, because the headers `spot.highlight.edges` and `spot.highlight.states` contain dots, which are disallowed in version 1. Compare these two outputs:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HOA: v1\n", + "States: 3\n", + "Start: 2\n", + "AP: 3 \"a\" \"b\" \"c\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "properties: trans-labels explicit-labels state-acc deterministic\n", + "properties: stutter-invariant terminal\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "State: 1\n", + "[2] 0\n", + "[1&!2] 1\n", + "State: 2\n", + "[2] 0\n", + "[!0&1&!2] 1\n", + "[0&!2] 2\n", + "--END--\n", + "\n", + "HOA: v1.1\n", + "States: 3\n", + "Start: 2\n", + "AP: 3 \"a\" \"b\" \"c\"\n", + "acc-name: Buchi\n", + "Acceptance: 1 Inf(0)\n", + "properties: trans-labels explicit-labels state-acc !complete\n", + "properties: deterministic stutter-invariant terminal\n", + "spot.highlight.states: 0 0 1 5 2 5\n", + "spot.highlight.edges: 2 1 4 1 5 1 6 2\n", + "--BODY--\n", + "State: 0 {0}\n", + "[t] 0\n", + "State: 1\n", + "[2] 0\n", + "[1&!2] 1\n", + "State: 2\n", + "[2] 0\n", + "[!0&1&!2] 1\n", + "[0&!2] 2\n", + "--END--\n" + ] + } + ], + "source": [ + "print(a.to_str('HOA', '1'))\n", + "print()\n", + "print(a.to_str('HOA', '1.1'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Highlighting a run\n", + "\n", + "One use of this highlighting is to highlight a run in an automaton.\n", + "\n", + "The following few command generate an automaton, then an accepting run on this automaton, and highlight that accepting run on the automaton. Note that a run knows the automaton from which it was generated, so calling `highlight()` will directly decorate that automaton." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d1b0> >" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b = spot.translate('X (F(Ga <-> b) & GF!b)'); b" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Prefix:\n", + " 0\n", + " | 1\n", + " 1\n", + " | !a & !b\n", + "Cycle:\n", + " 2\n", + " | !b\t{0}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r = b.accepting_run(); r" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "r.highlight(5) # the parameter is a color number" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The call of `highlight(5)` on the accepting run `r` modified the original automaton `b`:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d1b0> >" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Highlighting from a product\n", + "\n", + "Pretty often, accepting runs are found in a product but we want to display them on one of the original automata. This can be done by projecting the runs on those automata before displaying them." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d2d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d150> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = spot.translate('a U b')\n", + "right = spot.translate('GFa')\n", + "display(left, right)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d2a0> >" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prod = spot.product(left, right); prod" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Prefix:\n", + " 1,0\n", + " | !a & b\n", + "Cycle:\n", + " 0,0\n", + " | !a\t{0}\n", + " 0,0\n", + " | a\t{0,1}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run = prod.accepting_run(); run" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "run.highlight(5)\n", + "# Note that by default project() needs to know on which side you project, but it cannot \n", + "# guess it. The left-side is assumed unless you pass True as a second argument.\n", + "run.project(left).highlight(5)\n", + "run.project(right, True).highlight(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d2a0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d2d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d150> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(prod, left, right)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The projection also works for products generated on-the-fly, but the on-the-fly product itself cannot be highlighted (it does not store states or transitions). " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Prefix:\n", + " 0 * 3\n", + " | a & !b\n", + " 1 * 2\n", + " | a\t{0}\n", + " 1 * 1\n", + " | a\t{0}\n", + " 1 * 0\n", + " | a & b\t{0}\n", + "Cycle:\n", + " 1 * 4\n", + " | a\t{0,1}" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0 * 3\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1 * 2\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2\n", + "\n", + "2 * 2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "3\n", + "\n", + "1 * 1\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4\n", + "\n", + "2 * 1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "5\n", + "\n", + "1 * 0\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "6\n", + "\n", + "2 * 0\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "7\n", + "\n", + "1 * 4\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "8\n", + "\n", + "2 * 4\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "8->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d210> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d1e0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "I->3\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d270> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left2 = spot.translate('!b & FG a')\n", + "right2 = spot.translate('XXXb')\n", + "prod2 = spot.otf_product(left2, right2) # Note \"otf_product()\"\n", + "run2 = prod2.accepting_run()\n", + "run2.project(left2).highlight(5)\n", + "run2.project(right2, True).highlight(5)\n", + "display(run2, prod2, left2, right2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Highlighting nondeterminism\n", + "\n", + "Sometimes its is hard to locate non-deterministic states inside a large automaton. Here are two functions that can help for that." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d330> >" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b = spot.translate('X (F(Ga <-> b) & GF!b)')\n", + "spot.highlight_nondet_states(b, 5)\n", + "spot.highlight_nondet_edges(b, 4)\n", + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Disappearing highlights\n", + "\n", + "As explained at the top of this notebook, named properties (such as highlights) are fragile, and you should not really on them being preserved across algorithms. In-place algorithm are probably the worst, because they might modify the automaton and ignore the attached named properties. \n", + "\n", + "`randomize()` is one such in-place algorithm: it reorder states or transitions of the automaton. By doing so it renumber the states and edges, and that process would completely invalidate the highlights information. Fortunately `randomize()` know about highlights: it will preserve highlighted states, but it will drop all highlighted edges." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "I->4\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d330> >" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.randomize(b); b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Highlighting with partial output\n", + "\n", + "For simplicity, rendering of partial automata is actually implemented by copying the original automaton and marking some states as \"incomplete\". This also allows the same display code to work with automata generated on-the-fly. However since there is a copy, propagating the highlighting information requires extra work. Let's make sure it has been done:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "I->4\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe12058d330> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "4\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "u1\n", + "\n", + "...\n", + "\n", + "\n", + "1->u1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "3\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "2\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "u2\n", + "\n", + "...\n", + "\n", + "\n", + "2->u2\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "4\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a | b\n", + "\n", + "\n", + "u1\n", + "\n", + "...\n", + "\n", + "\n", + "1->u1\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "spot.highlight_nondet_edges(b, 4) # let's get those highlighted edges back\n", + "display(b, b.show('.<4'), b.show('.<2'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Highlighting languages\n", + "\n", + "For deterministic automata, the function `spot.highlight_languages()` can be used to highlight states that recognize the same language. This can be a great help in reading automata. States with a colored border share their language, and states with a black border all have a language different from all other states." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")\n", + "[Rabin 1]\n", + "cluster_0\n", + "\n", + "\n", + "cluster_1\n", + "\n", + "\n", + "cluster_2\n", + "\n", + "\n", + "cluster_3\n", + "\n", + "\n", + "cluster_4\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "6->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "7->6\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!a & b & !c\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "!a & b & c\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "5->1\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('(b W Xa) & GF(c <-> Xb) | a', 'generic', 'det')\n", + "spot.highlight_languages(aut)\n", + "aut.show('.bas')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,2476 +2526,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "spot.setup()\n", - "from IPython.display import display" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This notebook shows you different ways in which states or transitions can be highlighted in Spot. \n", - "\n", - "It should be noted that highlighting works using some special [named properties](https://spot.lrde.epita.fr/concepts.html#named-properties): basically, two maps that are attached to the automaton, and associated state or edge numbers to color numbers. This named properties are fragile: they will be lost if the automaton is transformed into a new automaton, and they can become meaningless of the automaton is modified in place (e.g., if the transitions or states are reordered).\n", - "\n", - "Nonetheless, highlighting is OK to use right before displaying or printing the automaton. The `dot` and `hoa` printer both know how to represent highlighted states and transitions.\n", - "\n", - "# Manual highlighting" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('a U b U c')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `#` option of `print_dot()` can be used to display the internal number of each transition " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.show('.#')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "#6\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "c\n", - "#4\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & b & !c\n", - "#5\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "#1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "c\n", - "#2\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "#3\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using these numbers you can selectively hightlight some transitions. The second argument is a color number (from a list of predefined colors)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.highlight_edges([2, 4, 5], 1)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & b & !c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe1205e8990> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that these `highlight_` functions work for edges and states, and come with both singular (changing the color of single state or edge) and plural versions.\n", - "\n", - "They modify the automaton in place." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.highlight_edge(6, 2).highlight_states((0, 1), 0)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & b & !c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe1205e8a80> >" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The plural version can take a list or tuple of state numbers (as above) or of Booleans (as below). In the latter case the indices of the True values give the states to highlight." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a.highlight_states([False, True, True], 5)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "I->2\n", - "\n", - "\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !c\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & b & !c\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe1205e8990> >" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Saving to HOA 1.1\n", - "\n", - "When saving to HOA format, the highlighting is only output if version 1.1 of the format is selected, because the headers `spot.highlight.edges` and `spot.highlight.states` contain dots, which are disallowed in version 1. Compare these two outputs:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(a.to_str('HOA', '1'))\n", - "print()\n", - "print(a.to_str('HOA', '1.1'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "HOA: v1\n", - "States: 3\n", - "Start: 2\n", - "AP: 3 \"a\" \"b\" \"c\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "properties: trans-labels explicit-labels state-acc deterministic\n", - "properties: stutter-invariant terminal\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "State: 1\n", - "[2] 0\n", - "[1&!2] 1\n", - "State: 2\n", - "[2] 0\n", - "[!0&1&!2] 1\n", - "[0&!2] 2\n", - "--END--\n", - "\n", - "HOA: v1.1\n", - "States: 3\n", - "Start: 2\n", - "AP: 3 \"a\" \"b\" \"c\"\n", - "acc-name: Buchi\n", - "Acceptance: 1 Inf(0)\n", - "properties: trans-labels explicit-labels state-acc !complete\n", - "properties: deterministic stutter-invariant terminal\n", - "spot.highlight.states: 0 0 1 5 2 5\n", - "spot.highlight.edges: 2 1 4 1 5 1 6 2\n", - "--BODY--\n", - "State: 0 {0}\n", - "[t] 0\n", - "State: 1\n", - "[2] 0\n", - "[1&!2] 1\n", - "State: 2\n", - "[2] 0\n", - "[!0&1&!2] 1\n", - "[0&!2] 2\n", - "--END--\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Highlighting a run\n", - "\n", - "One use of this highlighting is to highlight a run in an automaton.\n", - "\n", - "The following few command generate an automaton, then an accepting run on this automaton, and highlight that accepting run on the automaton. Note that a run knows the automaton from which it was generated, so calling `highlight()` will directly decorate that automaton." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "b = spot.translate('X (F(Ga <-> b) & GF!b)'); b" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d1b0> >" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "r = b.accepting_run(); r" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "Prefix:\n", - " 0\n", - " | 1\n", - " 1\n", - " | !a & !b\n", - "Cycle:\n", - " 2\n", - " | !b\t{0}" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "r.highlight(5) # the parameter is a color number" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The call of `highlight(5)` on the accepting run `r` modified the original automaton `b`:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "b" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d1b0> >" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Highlighting from a product\n", - "\n", - "Pretty often, accepting runs are found in a product but we want to display them on one of the original automata. This can be done by projecting the runs on those automata before displaying them." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "left = spot.translate('a U b')\n", - "right = spot.translate('GFa')\n", - "display(left, right)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d2d0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d150> >" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "prod = spot.product(left, right); prod" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "1,0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d2a0> >" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "run = prod.accepting_run(); run" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "Prefix:\n", - " 1,0\n", - " | !a & b\n", - "Cycle:\n", - " 0,0\n", - " | !a\t{0}\n", - " 0,0\n", - " | a\t{0,1}" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "run.highlight(5)\n", - "# Note that by default project() needs to know on which side you project, but it cannot \n", - "# guess it. The left-side is assumed unless you pass True as a second argument.\n", - "run.project(left).highlight(5)\n", - "run.project(right, True).highlight(5)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "display(prod, left, right)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "1,0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & b\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d2a0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d2d0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d150> >" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The projection also works for products generated on-the-fly, but the on-the-fly product itself cannot be highlighted (it does not store states or transitions). " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "left2 = spot.translate('!b & FG a')\n", - "right2 = spot.translate('XXXb')\n", - "prod2 = spot.otf_product(left2, right2) # Note \"otf_product()\"\n", - "run2 = prod2.accepting_run()\n", - "run2.project(left2).highlight(5)\n", - "run2.project(right2, True).highlight(5)\n", - "display(run2, prod2, left2, right2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "text": [ - "Prefix:\n", - " 0 * 3\n", - " | a & !b\n", - " 1 * 2\n", - " | a\t{0}\n", - " 1 * 1\n", - " | a\t{0}\n", - " 1 * 0\n", - " | a & b\t{0}\n", - "Cycle:\n", - " 1 * 4\n", - " | a\t{0,1}" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0 * 3\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1 * 2\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2\n", - "\n", - "2 * 2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "3\n", - "\n", - "1 * 1\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4\n", - "\n", - "2 * 1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "5\n", - "\n", - "1 * 0\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "6\n", - "\n", - "2 * 0\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "7\n", - "\n", - "1 * 4\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "8\n", - "\n", - "2 * 4\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "8->7\n", - "\n", - "\n", - "a\n", - "\u2776\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "1\n", - "\u2776\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d210> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d1e0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "I->3\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d270> >" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Highlighting nondeterminism\n", - "\n", - "Sometimes its is hard to locate non-deterministic states inside a large automaton. Here are two functions that can help for that." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "b = spot.translate('X (F(Ga <-> b) & GF!b)')\n", - "spot.highlight_nondet_states(b, 5)\n", - "spot.highlight_nondet_edges(b, 4)\n", - "b" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d330> >" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Disappearing highlights\n", - "\n", - "As explained at the top of this notebook, named properties (such as highlights) are fragile, and you should not really on them being preserved across algorithms. In-place algorithm are probably the worst, because they might modify the automaton and ignore the attached named properties. \n", - "\n", - "`randomize()` is one such in-place algorithm: it reorder states or transitions of the automaton. By doing so it renumber the states and edges, and that process would completely invalidate the highlights information. Fortunately `randomize()` know about highlights: it will preserve highlighted states, but it will drop all highlighted edges." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.randomize(b); b" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 19, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "I->4\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d330> >" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Highlighting with partial output\n", - "\n", - "For simplicity, rendering of partial automata is actually implemented by copying the original automaton and marking some states as \"incomplete\". This also allows the same display code to work with automata generated on-the-fly. However since there is a copy, propagating the highlighting information requires extra work. Let's make sure it has been done:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.highlight_nondet_edges(b, 4) # let's get those highlighted edges back\n", - "display(b, b.show('.<4'), b.show('.<2'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "I->4\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe12058d330> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "4\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "u1\n", - "\n", - "...\n", - "\n", - "\n", - "1->u1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "3\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "2\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "u2\n", - "\n", - "...\n", - "\n", - "\n", - "2->u2\n", - "\n", - "\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "4\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a | b\n", - "\n", - "\n", - "u1\n", - "\n", - "...\n", - "\n", - "\n", - "1->u1\n", - "\n", - "\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Highlighting languages\n", - "\n", - "For deterministic automata, the function `spot.highlight_languages()` can be used to highlight states that recognize the same language. This can be a great help in reading automata. States with a colored border share their language, and states with a black border all have a language different from all other states." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('(b W Xa) & GF(c <-> Xb) | a', 'generic', 'det')\n", - "spot.highlight_languages(aut)\n", - "aut.show('.bas')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 21, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & Inf(\n", - "\u2776\n", - ")\n", - "[Rabin 1]\n", - "cluster_0\n", - "\n", - "\n", - "cluster_1\n", - "\n", - "\n", - "cluster_2\n", - "\n", - "\n", - "cluster_3\n", - "\n", - "\n", - "cluster_4\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - "!c\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "c\n", - "\n", - "\n", - "6->4\n", - "\n", - "\n", - "!b\n", - "\u2776\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "b & c\n", - "\n", - "\n", - "7->4\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\n", - "\n", - "7->6\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "!b & c\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!a & b & !c\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "!a & b & c\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "5->1\n", - "\n", - "\n", - "!a & !b\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "!a & b\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 21 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/ipnbdoctest.py b/tests/python/ipnbdoctest.py index 59747354e..ae68deb10 100755 --- a/tests/python/ipnbdoctest.py +++ b/tests/python/ipnbdoctest.py @@ -8,11 +8,14 @@ Each cell is submitted to the kernel, and the outputs are compared with those stored in the notebook. """ +# Derived from https://gist.github.com/minrk/2620735 + from __future__ import print_function import os,sys,time import base64 import re +import pprint from difflib import unified_diff as diff from collections import defaultdict @@ -44,9 +47,9 @@ except ImportError: # Until Debian Stable ships IPython >3.0, we stick to the v3 format. try: - from nbformat import v3 as nbformat + from nbformat import v4 as nbformat except ImportError: - from IPython.nbformat import v3 as nbformat + from IPython.nbformat import v4 as nbformat def compare_png(a64, b64): """compare two b64 PNGs (incomplete)""" @@ -58,7 +61,7 @@ def compare_png(a64, b64): bdata = base64.decodestring(b64) return True -def sanitize(s): +def canonicalize(s, type, ignores): """sanitize a string for comparison. fix universal newlines, strip trailing newlines, and normalize likely @@ -85,6 +88,9 @@ def sanitize(s): s = re.sub(r'SpinS Promela Compiler.*Compiled C .* to .*pml.spins', 'SpinS output', s, flags=re.DOTALL) + # %%file writes `Writing`, or `Overwriting` if the file exists. + s = re.sub(r'^Overwriting ', 'Writing ', s) + # SVG generated by graphviz may put note at different positions # depending on the graphviz build. Let's just strip anything that # look like a position. @@ -115,47 +121,58 @@ def sanitize(s): # CalledProcessError message has a final dot in Python 3.6 s = re.sub(r"(' returned non-zero exit status \d+)\.", r'\1', s) + + for n, p in enumerate(ignores): + s = re.sub(p, 'IGN{}'.format(n), s) return s -def consolidate_outputs(outputs): - """consolidate outputs into a summary dict (incomplete)""" - data = defaultdict(list) - data['stdout'] = '' - data['stderr'] = '' +def canonical_dict(dict, ignores): + '''Neutralize gratuitous differences in a Jupyter dictionary. - for out in outputs: - if out.type == 'stream': - data[out.stream] += out.text - elif out.type == 'pyerr': - data['pyerr'] = dict(ename=out.ename, evalue=out.evalue) - else: - for key in ('png', 'svg', 'latex', 'html', - 'javascript', 'text', 'jpeg',): - if key in out: - data[key].append(out[key]) - return data + For instance, neutralize different Graphviz layouts in SVG. + ''' + + if 'text' in dict: + dict['text'] = canonicalize(dict['text'], 'text', ignores) + + if 'data' in dict: + for k in dict['data']: + dict['data'][k] = canonicalize(dict['data'][k], k, ignores) + + if ('ename' in dict and + dict['ename'] == 'SystemExit' and dict['evalue'] == '77'): + # sys.exit(77) is used to Skip the test. + sys.exit(77) + + if 'transient' in dict: + del dict['transient'] + if 'execution_count' in dict: + del dict['execution_count'] + if 'traceback' in dict: + del dict['traceback'] + return dict -def compare_outputs(test, ref, skip_cmp=('png', 'traceback', - 'latex', 'prompt_number')): - for key in ref: - if key not in test: - print("missing key: %s != %s" % (test.keys(), ref.keys())) - return False - elif key not in skip_cmp: - exp = sanitize(ref[key]) - eff = sanitize(test[key]) - if exp != eff: - print("mismatch %s:" % key) - if exp[:-1] != '\n': - exp += '\n' - if eff[:-1] != '\n': - eff += '\n' - print(''.join(diff(exp.splitlines(1), eff.splitlines(1), - fromfile='expected', tofile='effective'))) - return False - return True +def compare_outputs(ref, test, ignores=[]): + '''Check that two lists of outputs are equivalent and report the + result.''' + + # There can be several outputs. For instance wnen the cell both + # prints a result (goes to "stdout") and displays an automaton + # (goes to "data"). + exp = pprint.pformat([canonical_dict(d, ignores) for d in ref], width=132) + eff = pprint.pformat([canonical_dict(d, ignores) for d in test], width=132) + if exp[:-1] != '\n': + exp += '\n' + if eff[:-1] != '\n': + eff += '\n' + if exp == eff: + return True + else: + print(''.join(diff(exp.splitlines(1), eff.splitlines(1), + fromfile='expected', tofile='effective'))) + return False def _wait_for_ready_backport(kc): """Backport BlockingKernelClient.wait_for_ready from IPython 3""" @@ -173,8 +190,7 @@ def _wait_for_ready_backport(kc): break def run_cell(kc, cell): - # print cell.input - kc.execute(cell.input) + kc.execute(cell.source) # wait for finish, maximum 20s reply = kc.get_shell_msg(timeout=20) outs = [] @@ -184,52 +200,38 @@ def run_cell(kc, cell): msg = kc.get_iopub_msg(timeout=0.2) except Empty: break + msg_type = msg['msg_type'] - if msg_type in ('status', 'pyin', 'execute_input'): + content = msg['content'] + + if msg_type == 'status' and content['execution_state'] == 'idle': + break + if msg_type in ('status', 'pyin', 'execute_input', + 'comm_open', 'comm_msg'): continue + if msg_type == 'stream': + if 'Widget' in content['text']: + continue + # If the last stream had the same name, then outputs are + # appended. + if outs: + last = outs[-1] + if last['output_type'] == 'stream' and \ + last['name'] == content['name']: + last['text'] += content['text'] + continue elif msg_type == 'clear_output': outs = [] continue - content = msg['content'] - # print (msg_type, content) - if msg_type == 'execute_result': - msg_type = 'pyout' - elif msg_type == 'error': - msg_type = 'pyerr' - out = nbformat.NotebookNode(output_type=msg_type) - - if msg_type == 'stream': - out.stream = content['name'] - if 'text' in content: - out.text = content['text'] - else: - out.text = content['data'] - elif msg_type in ('display_data', 'pyout'): - out['metadata'] = content['metadata'] - for mime, data in content['data'].items(): - attr = mime.split('/')[-1].lower() - # this gets most right, but fix svg+html, plain - attr = attr.replace('+xml', '').replace('plain', 'text') - setattr(out, attr, data) - if 'execution_count' in content: - out.prompt_number = content['execution_count'] - elif msg_type == 'pyerr': - out.ename = content['ename'] - out.evalue = content['evalue'] - out.traceback = content['traceback'] - - # sys.exit(77) is used to Skip the test. - if out.ename == 'SystemExit' and out.evalue == '77': - sys.exit(77) - else: - print("unhandled iopub msg:", msg_type) - - outs.append(out) + content['output_type'] = msg_type + outs.append(content) return outs -def test_notebook(nb): +def test_notebook(ipynb): + with open(ipynb, encoding='utf-8') as f: + nb = nbformat.reads_json(f.read()) km = KernelManager() # Do not save the history to disk, as it can yield spurious lock errors. # See https://github.com/ipython/ipython/issues/2845 @@ -246,36 +248,34 @@ def test_notebook(nb): successes = 0 failures = 0 errors = 0 - for ws in nb.worksheets: - for i, cell in enumerate(ws.cells): - if cell.cell_type != 'code' or cell.input.startswith('%timeit'): - continue - try: - outs = run_cell(kc, cell) - except Exception as e: - print("failed to run cell:", repr(e)) - print(cell.input) - errors += 1 - continue + for i, cell in enumerate(nb.cells): + if cell.cell_type != 'code' or cell.source.startswith('%timeit'): + continue + try: + outs = run_cell(kc, cell) + except Exception as e: + print("failed to run cell:", repr(e)) + print(cell.input) + errors += 1 + continue - failed = False - if len(outs) != len(cell.outputs): - print("output length mismatch (expected {}, got {})".format( - len(cell.outputs), len(outs))) - failed = True - for out, ref in zip(outs, cell.outputs): - if not compare_outputs(out, ref): - failed = True - print("cell %d: " % i, end="") - if failed: - print("FAIL") - failures += 1 - else: - print("OK") - successes += 1 + failed = False + if len(outs) != len(cell.outputs): + print("output length mismatch (expected {}, got {})".format( + len(cell.outputs), len(outs))) + failed = True + if not compare_outputs(outs, cell.outputs): + failed = True + print("cell %d: " % i, end="") + if failed: + print("FAIL") + failures += 1 + else: + print("OK") + successes += 1 - print() - print("tested notebook %s" % nb.metadata.name) + + print("tested notebook %s" % ipynb) print(" %3i cells successfully replicated" % successes) if failures: print(" %3i cells mismatched output" % failures) @@ -290,6 +290,4 @@ def test_notebook(nb): if __name__ == '__main__': for ipynb in sys.argv[1:]: print("testing %s" % ipynb) - with open(ipynb) as f: - nb = nbformat.reads_json(f.read()) - test_notebook(nb) + test_notebook(ipynb) diff --git a/tests/python/ltsmin-dve.ipynb b/tests/python/ltsmin-dve.ipynb index 488757408..51d0978b3 100644 --- a/tests/python/ltsmin-dve.ipynb +++ b/tests/python/ltsmin-dve.ipynb @@ -1,4 +1,1531 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "import spot.ltsmin\n", + "# The following line causes the notebook to exit with 77 if divine is not \n", + "# installed, therefore skipping this test in the test suite.\n", + "spot.ltsmin.require('divine')\n", + "# This is notebook also tests the limitation of the number of states in the GraphViz output\n", + "spot.setup(max_states=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two ways to load a DiVinE model: from a file or from a cell. \n", + "\n", + "Loading from a file\n", + "-------------------\n", + "\n", + "We will first start with the file version, however because this notebook should also be a self-contained test case, we start by writing a model into a file." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!rm -f test1.dve" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing test1.dve\n" + ] + } + ], + "source": [ + "%%file test1.dve\n", + "int a = 0, b = 0;\n", + "\n", + "process P {\n", + " state x;\n", + " init x;\n", + "\n", + " trans\n", + " x -> x { guard a < 3 && b < 3; effect a = a + 1; },\n", + " x -> x { guard a < 3 && b < 3; effect b = b + 1; };\n", + "}\n", + "\n", + "process Q {\n", + " state wait, work;\n", + " init wait;\n", + " trans\n", + " wait -> work { guard b > 1; },\n", + " work -> wait { guard a > 1; };\n", + "}\n", + "\n", + "system async;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `spot.ltsmin.load` function compiles the model using the `ltlmin` interface and load it. This should work with DiVinE models if `divine --LTSmin` works, and with Promela models if `spins` is installed." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "m = spot.ltsmin.load('test1.dve')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compiling the model creates all several kinds of files. The `test1.dve` file is converted into a C++ source code `test1.dve.cpp` which is then compiled into a shared library `test1.dve2c`. Becauce `spot.ltsmin.load()` has already loaded this shared library, all those files can be erased. If you do not erase the files, `spot.ltsmin.load()` will use the timestamps to decide whether the library should be recompiled or not everytime you load the library.\n", + "\n", + "For editing and loading DVE file from a notebook, it is a better to use the `%%dve` as shown next." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!rm -f test1.dve test1.dve.cpp test1.dve2C" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Loading from a notebook cell\n", + "----------------------------\n", + "\n", + "The `%%dve` cell magic implements all of the above steps (saving the model into a temporary file, compiling it, loading it, erasing the temporary files). The variable name that should receive the model (here `m`) should be indicated on the first line, after `%dve`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%dve m\n", + "int a = 0, b = 0;\n", + "\n", + "process P {\n", + " state x;\n", + " init x;\n", + "\n", + " trans\n", + " x -> x { guard a < 3 && b < 3; effect a = a + 1; },\n", + " x -> x { guard a < 3 && b < 3; effect b = b + 1; };\n", + "}\n", + "\n", + "process Q {\n", + " state wait, work;\n", + " init wait;\n", + " trans\n", + " wait -> work { guard b > 1; },\n", + " work -> wait { guard a > 1; };\n", + "}\n", + "\n", + "system async;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Working with an ltsmin model\n", + "----------------------------\n", + "\n", + "Printing an ltsmin model shows some information about the variables it contains and their types, however the `info()` methods provide the data in a map that is easier to work with." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ltsmin model with the following variables:\n", + " a: int\n", + " b: int\n", + " P: ['x']\n", + " Q: ['wait', 'work']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('state_size', 4),\n", + " ('types', [('int', []), ('P', ['x']), ('Q', ['wait', 'work'])]),\n", + " ('variables', [('a', 0), ('b', 0), ('P', 1), ('Q', 2)])]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sorted(m.info().items())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To obtain a Kripke structure, call `kripke` and supply a list of atomic propositions to observe in the model." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "a=0, b=0, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "a=1, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "a=0, b=1, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "a=2, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "a=1, b=1, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "a=0, b=2, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "a=3, b=0, Q=0\n", + "!"a<1" & !"b>2" & dead\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "a=2, b=1, Q=0\n", + "...\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "a=1, b=2, Q=0\n", + "...\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "\n", + "\n", + "u5\n", + "\n", + "...\n", + "\n", + "\n", + "5->u5\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "a=0, b=3, Q=0\n", + "...\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "\n", + "\n", + "u7\n", + "\n", + "...\n", + "\n", + "\n", + "7->u7\n", + "\n", + "\n", + "\n", + "\n", + "u8\n", + "\n", + "...\n", + "\n", + "\n", + "8->u8\n", + "\n", + "\n", + "\n", + "\n", + "u9\n", + "\n", + "...\n", + "\n", + "\n", + "9->u9\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f402430f9c0> >" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "k = m.kripke([\"a<1\", \"b>2\"])\n", + "k" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "a=0, b=0, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "a=1, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "a=0, b=1, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "a=2, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "a=1, b=1, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "a=0, b=2, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "a=3, b=0, Q=0\n", + "!"a<1" & !"b>2" & dead\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "a=2, b=1, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "a=1, b=2, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "a=0, b=3, Q=0\n", + "...\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "\n", + "\n", + "10\n", + "\n", + "a=0, b=2, Q=1\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "5->10\n", + "\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "\n", + "\n", + "11\n", + "\n", + "a=3, b=1, Q=0\n", + "!"a<1" & !"b>2" & dead\n", + "\n", + "\n", + "7->11\n", + "\n", + "\n", + "\n", + "\n", + "12\n", + "\n", + "a=2, b=2, Q=0\n", + "...\n", + "\n", + "\n", + "7->12\n", + "\n", + "\n", + "\n", + "\n", + "8->12\n", + "\n", + "\n", + "\n", + "\n", + "13\n", + "\n", + "a=1, b=3, Q=0\n", + "...\n", + "\n", + "\n", + "8->13\n", + "\n", + "\n", + "\n", + "\n", + "14\n", + "\n", + "a=1, b=2, Q=1\n", + "...\n", + "\n", + "\n", + "8->14\n", + "\n", + "\n", + "\n", + "\n", + "u9\n", + "\n", + "...\n", + "\n", + "\n", + "9->u9\n", + "\n", + "\n", + "\n", + "\n", + "10->14\n", + "\n", + "\n", + "\n", + "\n", + "u10\n", + "\n", + "...\n", + "\n", + "\n", + "10->u10\n", + "\n", + "\n", + "\n", + "\n", + "11->11\n", + "\n", + "\n", + "\n", + "\n", + "u12\n", + "\n", + "...\n", + "\n", + "\n", + "12->u12\n", + "\n", + "\n", + "\n", + "\n", + "u13\n", + "\n", + "...\n", + "\n", + "\n", + "13->u13\n", + "\n", + "\n", + "\n", + "\n", + "u14\n", + "\n", + "...\n", + "\n", + "\n", + "14->u14\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "k.show('.<15')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "a=0, b=0, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "a=1, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "a=0, b=1, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "a=2, b=0, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "a=1, b=1, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "a=0, b=2, Q=0\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "a=3, b=0, Q=0\n", + "!"a<1" & !"b>2" & dead\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "a=2, b=1, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "a=1, b=2, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "a=0, b=3, Q=0\n", + ""a<1" & "b>2" & !dead\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "\n", + "\n", + "10\n", + "\n", + "a=0, b=2, Q=1\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "5->10\n", + "\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "\n", + "\n", + "11\n", + "\n", + "a=3, b=1, Q=0\n", + "!"a<1" & !"b>2" & dead\n", + "\n", + "\n", + "7->11\n", + "\n", + "\n", + "\n", + "\n", + "12\n", + "\n", + "a=2, b=2, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "7->12\n", + "\n", + "\n", + "\n", + "\n", + "8->12\n", + "\n", + "\n", + "\n", + "\n", + "13\n", + "\n", + "a=1, b=3, Q=0\n", + "!"a<1" & "b>2" & !dead\n", + "\n", + "\n", + "8->13\n", + "\n", + "\n", + "\n", + "\n", + "14\n", + "\n", + "a=1, b=2, Q=1\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "8->14\n", + "\n", + "\n", + "\n", + "\n", + "15\n", + "\n", + "a=0, b=3, Q=1\n", + ""a<1" & "b>2" & dead\n", + "\n", + "\n", + "9->15\n", + "\n", + "\n", + "\n", + "\n", + "10->14\n", + "\n", + "\n", + "\n", + "\n", + "10->15\n", + "\n", + "\n", + "\n", + "\n", + "11->11\n", + "\n", + "\n", + "\n", + "\n", + "16\n", + "\n", + "a=3, b=2, Q=0\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "12->16\n", + "\n", + "\n", + "\n", + "\n", + "17\n", + "\n", + "a=2, b=3, Q=0\n", + "!"a<1" & "b>2" & !dead\n", + "\n", + "\n", + "12->17\n", + "\n", + "\n", + "\n", + "\n", + "18\n", + "\n", + "a=2, b=2, Q=1\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "12->18\n", + "\n", + "\n", + "\n", + "\n", + "19\n", + "\n", + "a=1, b=3, Q=1\n", + "!"a<1" & "b>2" & dead\n", + "\n", + "\n", + "13->19\n", + "\n", + "\n", + "\n", + "\n", + "14->18\n", + "\n", + "\n", + "\n", + "\n", + "14->19\n", + "\n", + "\n", + "\n", + "\n", + "15->15\n", + "\n", + "\n", + "\n", + "\n", + "20\n", + "\n", + "a=3, b=2, Q=1\n", + "!"a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "16->20\n", + "\n", + "\n", + "\n", + "\n", + "21\n", + "\n", + "a=2, b=3, Q=1\n", + "!"a<1" & "b>2" & !dead\n", + "\n", + "\n", + "17->21\n", + "\n", + "\n", + "\n", + "\n", + "18->12\n", + "\n", + "\n", + "\n", + "\n", + "18->20\n", + "\n", + "\n", + "\n", + "\n", + "18->21\n", + "\n", + "\n", + "\n", + "\n", + "19->19\n", + "\n", + "\n", + "\n", + "\n", + "20->16\n", + "\n", + "\n", + "\n", + "\n", + "21->17\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "k.show('.<0') # unlimited output" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + ""a<1" & !"b>2"\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + ""b>2"\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f4024027150> >" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.translate('\"a<1\" U \"b>2\"'); a" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "a=0, b=0, Q=0 * 1\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "a=1, b=0, Q=0 * 1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "2\n", + "\n", + "a=0, b=1, Q=0 * 1\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "3\n", + "\n", + "a=1, b=1, Q=0 * 1\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "4\n", + "\n", + "a=0, b=2, Q=0 * 1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "5\n", + "\n", + "a=1, b=2, Q=0 * 1\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "6\n", + "\n", + "a=0, b=3, Q=0 * 1\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "7\n", + "\n", + "a=0, b=2, Q=1 * 1\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "8\n", + "\n", + "a=0, b=3, Q=1 * 0\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + ""a<1" & "b>2" & !dead\n", + "\n", + "\n", + "u7\n", + "\n", + "...\n", + "\n", + "\n", + "7->u7\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "a=1, b=2, Q=1 * 1\n", + "\n", + "\n", + "7->9\n", + "\n", + "\n", + ""a<1" & !"b>2" & !dead\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + ""a<1" & "b>2" & dead\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f402430ffc0> >" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.otf_product(k, a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to create a `model_check` function that takes a model and formula, we need to get the list of atomic propositions used in the formula using `atomic_prop_collect()`. This returns an `atomic_prop_set`:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\{``\\mathit{a < 2}\\textrm{''}, ``\\mathit{b == 1}\\textrm{''}\\}$" + ], + "text/plain": [ + "{\"a < 2\", \"b == 1\"}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = spot.atomic_prop_collect(spot.formula('\"a < 2\" W \"b == 1\"')); a" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def model_check(f, m):\n", + " f = spot.formula(f)\n", + " ss = m.kripke(spot.atomic_prop_collect(f))\n", + " nf = spot.formula_Not(f).translate()\n", + " return spot.otf_product(ss, nf).is_empty() " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model_check('\"a<1\" R \"b > 1\"', m)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead of `otf_product(x, y).is_empty()` we prefer to call `!x.intersects(y)`. There is also `x.intersecting_run(y)` that can be used to return a counterexample." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def model_debug(f, m):\n", + " f = spot.formula(f)\n", + " ss = m.kripke(spot.atomic_prop_collect(f))\n", + " nf = spot.formula_Not(f).translate()\n", + " return ss.intersecting_run(nf)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Prefix:\n", + " a=0, b=0, Q=0\n", + " | \"a<1\" & !\"b > 1\" & !dead\n", + " a=1, b=0, Q=0\n", + " | !\"a<1\" & !\"b > 1\" & !dead\n", + " a=2, b=0, Q=0\n", + " | !\"a<1\" & !\"b > 1\" & !dead\n", + "Cycle:\n", + " a=3, b=0, Q=0\n", + " | !\"a<1\" & !\"b > 1\" & dead" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run = model_debug('\"a<1\" R \"b > 1\"', m); run" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This accepting run can be represented as an automaton (the `True` argument requires the state names to be preserved). This can be more readable." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "a=0, b=0, Q=0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "a=1, b=0, Q=0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + ""a<1" & !"b > 1" & !dead\n", + "\n", + "\n", + "2\n", + "\n", + "a=2, b=0, Q=0\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!"a<1" & !"b > 1" & !dead\n", + "\n", + "\n", + "3\n", + "\n", + "a=3, b=0, Q=0\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!"a<1" & !"b > 1" & !dead\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!"a<1" & !"b > 1" & dead\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f4024027720> >" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run.as_twa(True)" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,1519 +1543,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "import spot.ltsmin\n", - "# The following line causes the notebook to exit with 77 if divine is not \n", - "# installed, therefore skipping this test in the test suite.\n", - "spot.ltsmin.require('divine')\n", - "# This is notebook also tests the limitation of the number of states in the GraphViz output\n", - "spot.setup(max_states=10)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are two ways to load a DiVinE model: from a file or from a cell. \n", - "\n", - "Loading from a file\n", - "-------------------\n", - "\n", - "We will first start with the file version, however because this notebook should also be a self-contained test case, we start by writing a model into a file." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!rm -f test1.dve" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%file test1.dve\n", - "int a = 0, b = 0;\n", - "\n", - "process P {\n", - " state x;\n", - " init x;\n", - "\n", - " trans\n", - " x -> x { guard a < 3 && b < 3; effect a = a + 1; },\n", - " x -> x { guard a < 3 && b < 3; effect b = b + 1; };\n", - "}\n", - "\n", - "process Q {\n", - " state wait, work;\n", - " init wait;\n", - " trans\n", - " wait -> work { guard b > 1; },\n", - " work -> wait { guard a > 1; };\n", - "}\n", - "\n", - "system async;" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Writing test1.dve\n" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `spot.ltsmin.load` function compiles the model using the `ltlmin` interface and load it. This should work with DiVinE models if `divine --LTSmin` works, and with Promela models if `spins` is installed." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "m = spot.ltsmin.load('test1.dve')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compiling the model creates all several kinds of files. The `test1.dve` file is converted into a C++ source code `test1.dve.cpp` which is then compiled into a shared library `test1.dve2c`. Becauce `spot.ltsmin.load()` has already loaded this shared library, all those files can be erased. If you do not erase the files, `spot.ltsmin.load()` will use the timestamps to decide whether the library should be recompiled or not everytime you load the library.\n", - "\n", - "For editing and loading DVE file from a notebook, it is a better to use the `%%dve` as shown next." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!rm -f test1.dve test1.dve.cpp test1.dve2C" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Loading from a notebook cell\n", - "----------------------------\n", - "\n", - "The `%%dve` cell magic implements all of the above steps (saving the model into a temporary file, compiling it, loading it, erasing the temporary files). The variable name that should receive the model (here `m`) should be indicated on the first line, after `%dve`." - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "%%dve m\n", - "int a = 0, b = 0;\n", - "\n", - "process P {\n", - " state x;\n", - " init x;\n", - "\n", - " trans\n", - " x -> x { guard a < 3 && b < 3; effect a = a + 1; },\n", - " x -> x { guard a < 3 && b < 3; effect b = b + 1; };\n", - "}\n", - "\n", - "process Q {\n", - " state wait, work;\n", - " init wait;\n", - " trans\n", - " wait -> work { guard b > 1; },\n", - " work -> wait { guard a > 1; };\n", - "}\n", - "\n", - "system async;" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Working with an ltsmin model\n", - "----------------------------\n", - "\n", - "Printing an ltsmin model shows some information about the variables it contains and their types, however the `info()` methods provide the data in a map that is easier to work with." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "m" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 7, - "text": [ - "ltsmin model with the following variables:\n", - " a: int\n", - " b: int\n", - " P: ['x']\n", - " Q: ['wait', 'work']" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sorted(m.info().items())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "[('state_size', 4),\n", - " ('types', [('int', []), ('P', ['x']), ('Q', ['wait', 'work'])]),\n", - " ('variables', [('a', 0), ('b', 0), ('P', 1), ('Q', 2)])]" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To obtain a Kripke structure, call `kripke` and supply a list of atomic propositions to observe in the model." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "k = m.kripke([\"a<1\", \"b>2\"])\n", - "k" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "a=0, b=0, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "a=1, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "a=0, b=1, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "a=2, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "a=1, b=1, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "a=0, b=2, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "a=3, b=0, Q=0\n", - "!"a<1" & !"b>2" & dead\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "a=2, b=1, Q=0\n", - "...\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "a=1, b=2, Q=0\n", - "...\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "\n", - "\n", - "u5\n", - "\n", - "...\n", - "\n", - "\n", - "5->u5\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "a=0, b=3, Q=0\n", - "...\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "\n", - "\n", - "u7\n", - "\n", - "...\n", - "\n", - "\n", - "7->u7\n", - "\n", - "\n", - "\n", - "\n", - "u8\n", - "\n", - "...\n", - "\n", - "\n", - "8->u8\n", - "\n", - "\n", - "\n", - "\n", - "u9\n", - "\n", - "...\n", - "\n", - "\n", - "9->u9\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f402430f9c0> >" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "k.show('.<15')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "a=0, b=0, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "a=1, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "a=0, b=1, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "a=2, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "a=1, b=1, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "a=0, b=2, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "a=3, b=0, Q=0\n", - "!"a<1" & !"b>2" & dead\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "a=2, b=1, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "a=1, b=2, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "a=0, b=3, Q=0\n", - "...\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "\n", - "\n", - "10\n", - "\n", - "a=0, b=2, Q=1\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "5->10\n", - "\n", - "\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "\n", - "\n", - "11\n", - "\n", - "a=3, b=1, Q=0\n", - "!"a<1" & !"b>2" & dead\n", - "\n", - "\n", - "7->11\n", - "\n", - "\n", - "\n", - "\n", - "12\n", - "\n", - "a=2, b=2, Q=0\n", - "...\n", - "\n", - "\n", - "7->12\n", - "\n", - "\n", - "\n", - "\n", - "8->12\n", - "\n", - "\n", - "\n", - "\n", - "13\n", - "\n", - "a=1, b=3, Q=0\n", - "...\n", - "\n", - "\n", - "8->13\n", - "\n", - "\n", - "\n", - "\n", - "14\n", - "\n", - "a=1, b=2, Q=1\n", - "...\n", - "\n", - "\n", - "8->14\n", - "\n", - "\n", - "\n", - "\n", - "u9\n", - "\n", - "...\n", - "\n", - "\n", - "9->u9\n", - "\n", - "\n", - "\n", - "\n", - "10->14\n", - "\n", - "\n", - "\n", - "\n", - "u10\n", - "\n", - "...\n", - "\n", - "\n", - "10->u10\n", - "\n", - "\n", - "\n", - "\n", - "11->11\n", - "\n", - "\n", - "\n", - "\n", - "u12\n", - "\n", - "...\n", - "\n", - "\n", - "12->u12\n", - "\n", - "\n", - "\n", - "\n", - "u13\n", - "\n", - "...\n", - "\n", - "\n", - "13->u13\n", - "\n", - "\n", - "\n", - "\n", - "u14\n", - "\n", - "...\n", - "\n", - "\n", - "14->u14\n", - "\n", - "\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "k.show('.<0') # unlimited output" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "a=0, b=0, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "a=1, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "a=0, b=1, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "a=2, b=0, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "a=1, b=1, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "a=0, b=2, Q=0\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "a=3, b=0, Q=0\n", - "!"a<1" & !"b>2" & dead\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "a=2, b=1, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "a=1, b=2, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "a=0, b=3, Q=0\n", - ""a<1" & "b>2" & !dead\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "\n", - "\n", - "10\n", - "\n", - "a=0, b=2, Q=1\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "5->10\n", - "\n", - "\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "\n", - "\n", - "11\n", - "\n", - "a=3, b=1, Q=0\n", - "!"a<1" & !"b>2" & dead\n", - "\n", - "\n", - "7->11\n", - "\n", - "\n", - "\n", - "\n", - "12\n", - "\n", - "a=2, b=2, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "7->12\n", - "\n", - "\n", - "\n", - "\n", - "8->12\n", - "\n", - "\n", - "\n", - "\n", - "13\n", - "\n", - "a=1, b=3, Q=0\n", - "!"a<1" & "b>2" & !dead\n", - "\n", - "\n", - "8->13\n", - "\n", - "\n", - "\n", - "\n", - "14\n", - "\n", - "a=1, b=2, Q=1\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "8->14\n", - "\n", - "\n", - "\n", - "\n", - "15\n", - "\n", - "a=0, b=3, Q=1\n", - ""a<1" & "b>2" & dead\n", - "\n", - "\n", - "9->15\n", - "\n", - "\n", - "\n", - "\n", - "10->14\n", - "\n", - "\n", - "\n", - "\n", - "10->15\n", - "\n", - "\n", - "\n", - "\n", - "11->11\n", - "\n", - "\n", - "\n", - "\n", - "16\n", - "\n", - "a=3, b=2, Q=0\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "12->16\n", - "\n", - "\n", - "\n", - "\n", - "17\n", - "\n", - "a=2, b=3, Q=0\n", - "!"a<1" & "b>2" & !dead\n", - "\n", - "\n", - "12->17\n", - "\n", - "\n", - "\n", - "\n", - "18\n", - "\n", - "a=2, b=2, Q=1\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "12->18\n", - "\n", - "\n", - "\n", - "\n", - "19\n", - "\n", - "a=1, b=3, Q=1\n", - "!"a<1" & "b>2" & dead\n", - "\n", - "\n", - "13->19\n", - "\n", - "\n", - "\n", - "\n", - "14->18\n", - "\n", - "\n", - "\n", - "\n", - "14->19\n", - "\n", - "\n", - "\n", - "\n", - "15->15\n", - "\n", - "\n", - "\n", - "\n", - "20\n", - "\n", - "a=3, b=2, Q=1\n", - "!"a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "16->20\n", - "\n", - "\n", - "\n", - "\n", - "21\n", - "\n", - "a=2, b=3, Q=1\n", - "!"a<1" & "b>2" & !dead\n", - "\n", - "\n", - "17->21\n", - "\n", - "\n", - "\n", - "\n", - "18->12\n", - "\n", - "\n", - "\n", - "\n", - "18->20\n", - "\n", - "\n", - "\n", - "\n", - "18->21\n", - "\n", - "\n", - "\n", - "\n", - "19->19\n", - "\n", - "\n", - "\n", - "\n", - "20->16\n", - "\n", - "\n", - "\n", - "\n", - "21->17\n", - "\n", - "\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.translate('\"a<1\" U \"b>2\"'); a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - ""a<1" & !"b>2"\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - ""b>2"\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f4024027150> >" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.otf_product(k, a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "a=0, b=0, Q=0 * 1\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "a=1, b=0, Q=0 * 1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "2\n", - "\n", - "a=0, b=1, Q=0 * 1\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "3\n", - "\n", - "a=1, b=1, Q=0 * 1\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "4\n", - "\n", - "a=0, b=2, Q=0 * 1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "5\n", - "\n", - "a=1, b=2, Q=0 * 1\n", - "\n", - "\n", - "4->5\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "6\n", - "\n", - "a=0, b=3, Q=0 * 1\n", - "\n", - "\n", - "4->6\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "7\n", - "\n", - "a=0, b=2, Q=1 * 1\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "8\n", - "\n", - "a=0, b=3, Q=1 * 0\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - ""a<1" & "b>2" & !dead\n", - "\n", - "\n", - "u7\n", - "\n", - "...\n", - "\n", - "\n", - "7->u7\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "a=1, b=2, Q=1 * 1\n", - "\n", - "\n", - "7->9\n", - "\n", - "\n", - ""a<1" & !"b>2" & !dead\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - ""a<1" & "b>2" & dead\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f402430ffc0> >" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we want to create a `model_check` function that takes a model and formula, we need to get the list of atomic propositions used in the formula using `atomic_prop_collect()`. This returns an `atomic_prop_set`:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a = spot.atomic_prop_collect(spot.formula('\"a < 2\" W \"b == 1\"')); a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\{``\\mathit{a < 2}\\textrm{''}, ``\\mathit{b == 1}\\textrm{''}\\}$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "{\"a < 2\", \"b == 1\"}" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def model_check(f, m):\n", - " f = spot.formula(f)\n", - " ss = m.kripke(spot.atomic_prop_collect(f))\n", - " nf = spot.formula_Not(f).translate()\n", - " return spot.otf_product(ss, nf).is_empty() " - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "model_check('\"a<1\" R \"b > 1\"', m)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "text": [ - "False" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instead of `otf_product(x, y).is_empty()` we prefer to call `!x.intersects(y)`. There is also `x.intersecting_run(y)` that can be used to return a counterexample." - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "def model_debug(f, m):\n", - " f = spot.formula(f)\n", - " ss = m.kripke(spot.atomic_prop_collect(f))\n", - " nf = spot.formula_Not(f).translate()\n", - " return ss.intersecting_run(nf)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 21 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "run = model_debug('\"a<1\" R \"b > 1\"', m); run" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 23, - "text": [ - "Prefix:\n", - " a=0, b=0, Q=0\n", - " | \"a<1\" & !\"b > 1\" & !dead\n", - " a=1, b=0, Q=0\n", - " | !\"a<1\" & !\"b > 1\" & !dead\n", - " a=2, b=0, Q=0\n", - " | !\"a<1\" & !\"b > 1\" & !dead\n", - "Cycle:\n", - " a=3, b=0, Q=0\n", - " | !\"a<1\" & !\"b > 1\" & dead" - ] - } - ], - "prompt_number": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This accepting run can be represented as an automaton (the `True` argument requires the state names to be preserved). This can be more readable." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "run.as_twa(True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 24, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "a=0, b=0, Q=0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "a=1, b=0, Q=0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - ""a<1" & !"b > 1" & !dead\n", - "\n", - "\n", - "2\n", - "\n", - "a=2, b=0, Q=0\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!"a<1" & !"b > 1" & !dead\n", - "\n", - "\n", - "3\n", - "\n", - "a=3, b=0, Q=0\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!"a<1" & !"b > 1" & !dead\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!"a<1" & !"b > 1" & dead\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f4024027720> >" - ] - } - ], - "prompt_number": 24 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/ltsmin-pml.ipynb b/tests/python/ltsmin-pml.ipynb index 26ba73717..1e6140d55 100644 --- a/tests/python/ltsmin-pml.ipynb +++ b/tests/python/ltsmin-pml.ipynb @@ -1,4 +1,649 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "import spot.ltsmin\n", + "# The following line causes the notebook to exit with 77 if spins is not \n", + "# installed, therefore skipping this test in the test suite.\n", + "spot.ltsmin.require('spins')\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two ways to load a Promela model: from a file or from a cell. \n", + "\n", + "Loading from a cell\n", + "-------------------\n", + "\n", + "Using the `%%pml` magic will save the model in a temporary file, call `spins` to compile it, load the resulting shared library, and store the result into an object whose name is passed as an argument to `%%pml`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "SpinS Promela Compiler - version 1.1 (3-Feb-2015)\n", + "(C) University of Twente, Formal Methods and Tools group\n", + "\n", + "Parsing tmpmmk02hmw.pml...\n", + "Parsing tmpmmk02hmw.pml done (0.0 sec)\n", + "\n", + "Optimizing graphs...\n", + " StateMerging changed 0 states/transitions.\n", + " RemoveUselessActions changed 2 states/transitions.\n", + " RemoveUselessGotos changed 2 states/transitions.\n", + " RenumberAll changed 1 states/transitions.\n", + "Optimization done (0.0 sec)\n", + "\n", + "Generating next-state function ...\n", + " Instantiating processes\n", + " Statically binding references\n", + " Creating transitions\n", + "Generating next-state function done (0.0 sec)\n", + "\n", + "Creating state vector\n", + "Creating state labels\n", + "Generating transitions/state dependency matrices (2 / 3 slots) ... \n", + "\n", + " [.......... ]\n", + " [.................... ]\n", + " [.............................. ]\n", + " [........................................ ]\n", + " [..................................................]\n", + " Found 5 / 15 ( 33.3%) Guard/slot reads \n", + "\n", + " [......................... ]\n", + " [..................................................]\n", + " Found 6 / 6 (100.0%) Transition/slot tests \n", + "\n", + " [........ ]\n", + " [................ ]\n", + " [......................... ]\n", + " [................................. ]\n", + " [......................................... ]\n", + " [..................................................]\n", + " Found 2, 4, 4 / 18 ( 11.1%, 22.2%, 22.2%) Actions/slot r,W,w \n", + "\n", + " [......................... ]\n", + " [..................................................]\n", + " Found 2, 4, 4 / 6 ( 33.3%, 66.7%, 66.7%) Atomics/slot r,W,w \n", + "\n", + " [......................... ]\n", + " [..................................................]\n", + " Found 6, 4, 4 / 6 (100.0%, 66.7%, 66.7%) Transition/slot r,W,w \n", + "Generating transition/state dependency matrices done (0.0 sec)\n", + "\n", + "Generating guard dependency matrices (5 guards) ...\n", + "\n", + " [.... ]\n", + " [........ ]\n", + " [............ ]\n", + " [................ ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [............................. ]\n", + " [................................. ]\n", + " [..................................... ]\n", + " [......................................... ]\n", + " Found 3 / 12 ( 25.0%) Guard/guard dependencies \n", + "\n", + " [..... ]\n", + " [.......... ]\n", + " [............... ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [.............................. ]\n", + " [................................... ]\n", + " [........................................ ]\n", + " [............................................. ]\n", + " [..................................................]\n", + " Found 8 / 10 ( 80.0%) Transition/guard writes \n", + "\n", + " Found 4 / 4 (100.0%) Transition/transition writes \n", + "\n", + " [.... ]\n", + " [........ ]\n", + " [............ ]\n", + " [................ ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [............................. ]\n", + " [................................. ]\n", + " [..................................... ]\n", + " [......................................... ]\n", + " Found 2 / 12 ( 16.7%) !MCE guards \n", + "\n", + " [......................... ]\n", + " Found 1 / 2 ( 50.0%) !MCE transitions \n", + "\n", + " [.. ]\n", + " [.... ]\n", + " [...... ]\n", + " [........ ]\n", + " [.......... ]\n", + " [............ ]\n", + " [.............. ]\n", + " [................ ]\n", + " [.................. ]\n", + " [.................... ]\n", + " [...................... ]\n", + " [........................ ]\n", + " [.......................... ]\n", + " [............................ ]\n", + " [.............................. ]\n", + " [................................ ]\n", + " [.................................. ]\n", + " [.................................... ]\n", + " [...................................... ]\n", + " [........................................ ]\n", + " [.......................................... ]\n", + " [............................................ ]\n", + " [.............................................. ]\n", + " [................................................ ]\n", + " [..................................................]\n", + " Found 7 / 25 ( 28.0%) !ICE guards \n", + "\n", + " [..... ]\n", + " [.......... ]\n", + " [............... ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [.............................. ]\n", + " [................................... ]\n", + " [........................................ ]\n", + " [............................................. ]\n", + " [..................................................]\n", + " Found 10 / 10 (100.0%) !NES guards \n", + "\n", + " [............ ]\n", + " [......................... ]\n", + " [..................................... ]\n", + " [..................................................]\n", + " Found 4 / 4 (100.0%) !NES transitions \n", + "\n", + " [..... ]\n", + " [.......... ]\n", + " [............... ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [.............................. ]\n", + " [................................... ]\n", + " [........................................ ]\n", + " [............................................. ]\n", + " [..................................................]\n", + " Found 8 / 10 ( 80.0%) !NDS guards \n", + "\n", + " [..... ]\n", + " [.......... ]\n", + " [............... ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [.............................. ]\n", + " [................................... ]\n", + " [........................................ ]\n", + " [............................................. ]\n", + " [..................................................]\n", + " Found 0 / 10 ( 0.0%) MDS guards \n", + "\n", + " [..... ]\n", + " [.......... ]\n", + " [............... ]\n", + " [.................... ]\n", + " [......................... ]\n", + " [.............................. ]\n", + " [................................... ]\n", + " [........................................ ]\n", + " [............................................. ]\n", + " [..................................................]\n", + " Found 4 / 10 ( 40.0%) MES guards \n", + "\n", + " [............ ]\n", + " [......................... ]\n", + " [..................................... ]\n", + " [..................................................]\n", + " Found 0 / 4 ( 0.0%) !NDS transitions \n", + "\n", + " [......................... ]\n", + " Found 0 / 2 ( 0.0%) !DNA transitions \n", + "\n", + " [......................... ]\n", + " [..................................................]\n", + " [..................................................]\n", + " Found 2 / 2 (100.0%) Commuting actions \n", + "Generating guard dependency matrices done (0.0 sec)\n", + "\n", + "Written C code to /home/adl/git/spot/tests/python/tmpmmk02hmw.pml.spins.c\n", + "Compiled C code to PINS library tmpmmk02hmw.pml.spins\n", + "\n" + ] + } + ], + "source": [ + "%%pml model\n", + "active proctype P() {\n", + "int a = 0;\n", + "int b = 0;\n", + "x: if\n", + " :: d_step {a < 3 && b < 3; a = a + 1; } goto x;\n", + " :: d_step {a < 3 && b < 3; b = b + 1; } goto x;\n", + "fi;\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yes, the `spins` compiler is quite verbose. Printing the resulting `model` object will show information about the variables in that model. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ltsmin model with the following variables:\n", + " P_0._pc: pc\n", + " P_0.a: int\n", + " P_0.b: int" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To instantiate a Kripke structure, one should provide a list of atomic proposition to observe." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "P_0._pc=0, P_0.a=0, P_0.b=0\n", + ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "P_0._pc=0, P_0.a=1, P_0.b=0\n", + ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "P_0._pc=0, P_0.a=0, P_0.b=1\n", + ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "P_0._pc=0, P_0.a=2, P_0.b=0\n", + "!"P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "P_0._pc=0, P_0.a=1, P_0.b=1\n", + ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "P_0._pc=0, P_0.a=0, P_0.b=2\n", + ""P_0.a < 2" & "P_0.b > 1" & !dead\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "P_0._pc=0, P_0.a=3, P_0.b=0\n", + "!"P_0.a < 2" & !"P_0.b > 1" & dead\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "P_0._pc=0, P_0.a=2, P_0.b=1\n", + "!"P_0.a < 2" & !"P_0.b > 1" & !dead\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "P_0._pc=0, P_0.a=1, P_0.b=2\n", + ""P_0.a < 2" & "P_0.b > 1" & !dead\n", + "\n", + "\n", + "4->8\n", + "\n", + "\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "P_0._pc=0, P_0.a=0, P_0.b=3\n", + ""P_0.a < 2" & "P_0.b > 1" & dead\n", + "\n", + "\n", + "5->9\n", + "\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "\n", + "\n", + "10\n", + "\n", + "P_0._pc=0, P_0.a=3, P_0.b=1\n", + "!"P_0.a < 2" & !"P_0.b > 1" & dead\n", + "\n", + "\n", + "7->10\n", + "\n", + "\n", + "\n", + "\n", + "11\n", + "\n", + "P_0._pc=0, P_0.a=2, P_0.b=2\n", + "!"P_0.a < 2" & "P_0.b > 1" & !dead\n", + "\n", + "\n", + "7->11\n", + "\n", + "\n", + "\n", + "\n", + "8->11\n", + "\n", + "\n", + "\n", + "\n", + "12\n", + "\n", + "P_0._pc=0, P_0.a=1, P_0.b=3\n", + ""P_0.a < 2" & "P_0.b > 1" & dead\n", + "\n", + "\n", + "8->12\n", + "\n", + "\n", + "\n", + "\n", + "9->9\n", + "\n", + "\n", + "\n", + "\n", + "10->10\n", + "\n", + "\n", + "\n", + "\n", + "13\n", + "\n", + "P_0._pc=0, P_0.a=3, P_0.b=2\n", + "!"P_0.a < 2" & "P_0.b > 1" & dead\n", + "\n", + "\n", + "11->13\n", + "\n", + "\n", + "\n", + "\n", + "14\n", + "\n", + "P_0._pc=0, P_0.a=2, P_0.b=3\n", + "!"P_0.a < 2" & "P_0.b > 1" & dead\n", + "\n", + "\n", + "11->14\n", + "\n", + "\n", + "\n", + "\n", + "12->12\n", + "\n", + "\n", + "\n", + "\n", + "13->13\n", + "\n", + "\n", + "\n", + "\n", + "14->14\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fe0808e0240> >" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "k = model.kripke(['P_0.a < 2', 'P_0.b > 1']); k" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then from this Kripke structure you can do some model checking using the same functions as illustrated in `ltsmin-dve.ipynb`.\n", + "\n", + "Loading from a `*.pml` file\n", + "---------------------------\n", + "\n", + "Another option is to use `ltsmin.load()` to load a Promela file directly. In order for this test-case to be self-contained, we are going to write the Promela file first, but in practice you probably already have your model." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!rm -rf test1.pml" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing test1.pml\n" + ] + } + ], + "source": [ + "%%file test1.pml\n", + "active proctype P() {\n", + "int a = 0;\n", + "int b = 0;\n", + "x: if\n", + " :: d_step {a < 3 && b < 3; a = a + 1; } goto x;\n", + " :: d_step {a < 3 && b < 3; b = b + 1; } goto x;\n", + "fi;\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now load it:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model2 = spot.ltsmin.load('test1.pml')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ltsmin model with the following variables:\n", + " P_0._pc: pc\n", + " P_0.a: int\n", + " P_0.b: int" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model2" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!rm -f test1.pml test1.pml.spins.c test1.pml.spins" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,654 +661,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" - }, - "name": "", - "signature": "sha256:07d2378b77f0b3c281fb9907deb011c1716ab64dab3726379c60ae42d5f4dd80" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "import spot.ltsmin\n", - "# The following line causes the notebook to exit with 77 if spins is not \n", - "# installed, therefore skipping this test in the test suite.\n", - "spot.ltsmin.require('spins')\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are two ways to load a Promela model: from a file or from a cell. \n", - "\n", - "Loading from a cell\n", - "-------------------\n", - "\n", - "Using the `%%pml` magic will save the model in a temporary file, call `spins` to compile it, load the resulting shared library, and store the result into an object whose name is passed as an argument to `%%pml`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%pml model\n", - "active proctype P() {\n", - "int a = 0;\n", - "int b = 0;\n", - "x: if\n", - " :: d_step {a < 3 && b < 3; a = a + 1; } goto x;\n", - " :: d_step {a < 3 && b < 3; b = b + 1; } goto x;\n", - "fi;\n", - "}" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stderr", - "text": [ - "SpinS Promela Compiler - version 1.1 (3-Feb-2015)\n", - "(C) University of Twente, Formal Methods and Tools group\n", - "\n", - "Parsing tmpmmk02hmw.pml...\n", - "Parsing tmpmmk02hmw.pml done (0.0 sec)\n", - "\n", - "Optimizing graphs...\n", - " StateMerging changed 0 states/transitions.\n", - " RemoveUselessActions changed 2 states/transitions.\n", - " RemoveUselessGotos changed 2 states/transitions.\n", - " RenumberAll changed 1 states/transitions.\n", - "Optimization done (0.0 sec)\n", - "\n", - "Generating next-state function ...\n", - " Instantiating processes\n", - " Statically binding references\n", - " Creating transitions\n", - "Generating next-state function done (0.0 sec)\n", - "\n", - "Creating state vector\n", - "Creating state labels\n", - "Generating transitions/state dependency matrices (2 / 3 slots) ... \n", - "\n", - " [.......... ]\n", - " [.................... ]\n", - " [.............................. ]\n", - " [........................................ ]\n", - " [..................................................]\n", - " Found 5 / 15 ( 33.3%) Guard/slot reads \n", - "\n", - " [......................... ]\n", - " [..................................................]\n", - " Found 6 / 6 (100.0%) Transition/slot tests \n", - "\n", - " [........ ]\n", - " [................ ]\n", - " [......................... ]\n", - " [................................. ]\n", - " [......................................... ]\n", - " [..................................................]\n", - " Found 2, 4, 4 / 18 ( 11.1%, 22.2%, 22.2%) Actions/slot r,W,w \n", - "\n", - " [......................... ]\n", - " [..................................................]\n", - " Found 2, 4, 4 / 6 ( 33.3%, 66.7%, 66.7%) Atomics/slot r,W,w \n", - "\n", - " [......................... ]\n", - " [..................................................]\n", - " Found 6, 4, 4 / 6 (100.0%, 66.7%, 66.7%) Transition/slot r,W,w \n", - "Generating transition/state dependency matrices done (0.0 sec)\n", - "\n", - "Generating guard dependency matrices (5 guards) ...\n", - "\n", - " [.... ]\n", - " [........ ]\n", - " [............ ]\n", - " [................ ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [............................. ]\n", - " [................................. ]\n", - " [..................................... ]\n", - " [......................................... ]\n", - " Found 3 / 12 ( 25.0%) Guard/guard dependencies \n", - "\n", - " [..... ]\n", - " [.......... ]\n", - " [............... ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [.............................. ]\n", - " [................................... ]\n", - " [........................................ ]\n", - " [............................................. ]\n", - " [..................................................]\n", - " Found 8 / 10 ( 80.0%) Transition/guard writes \n", - "\n", - " Found 4 / 4 (100.0%) Transition/transition writes \n", - "\n", - " [.... ]\n", - " [........ ]\n", - " [............ ]\n", - " [................ ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [............................. ]\n", - " [................................. ]\n", - " [..................................... ]\n", - " [......................................... ]\n", - " Found 2 / 12 ( 16.7%) !MCE guards \n", - "\n", - " [......................... ]\n", - " Found 1 / 2 ( 50.0%) !MCE transitions \n", - "\n", - " [.. ]\n", - " [.... ]\n", - " [...... ]\n", - " [........ ]\n", - " [.......... ]\n", - " [............ ]\n", - " [.............. ]\n", - " [................ ]\n", - " [.................. ]\n", - " [.................... ]\n", - " [...................... ]\n", - " [........................ ]\n", - " [.......................... ]\n", - " [............................ ]\n", - " [.............................. ]\n", - " [................................ ]\n", - " [.................................. ]\n", - " [.................................... ]\n", - " [...................................... ]\n", - " [........................................ ]\n", - " [.......................................... ]\n", - " [............................................ ]\n", - " [.............................................. ]\n", - " [................................................ ]\n", - " [..................................................]\n", - " Found 7 / 25 ( 28.0%) !ICE guards \n", - "\n", - " [..... ]\n", - " [.......... ]\n", - " [............... ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [.............................. ]\n", - " [................................... ]\n", - " [........................................ ]\n", - " [............................................. ]\n", - " [..................................................]\n", - " Found 10 / 10 (100.0%) !NES guards \n", - "\n", - " [............ ]\n", - " [......................... ]\n", - " [..................................... ]\n", - " [..................................................]\n", - " Found 4 / 4 (100.0%) !NES transitions \n", - "\n", - " [..... ]\n", - " [.......... ]\n", - " [............... ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [.............................. ]\n", - " [................................... ]\n", - " [........................................ ]\n", - " [............................................. ]\n", - " [..................................................]\n", - " Found 8 / 10 ( 80.0%) !NDS guards \n", - "\n", - " [..... ]\n", - " [.......... ]\n", - " [............... ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [.............................. ]\n", - " [................................... ]\n", - " [........................................ ]\n", - " [............................................. ]\n", - " [..................................................]\n", - " Found 0 / 10 ( 0.0%) MDS guards \n", - "\n", - " [..... ]\n", - " [.......... ]\n", - " [............... ]\n", - " [.................... ]\n", - " [......................... ]\n", - " [.............................. ]\n", - " [................................... ]\n", - " [........................................ ]\n", - " [............................................. ]\n", - " [..................................................]\n", - " Found 4 / 10 ( 40.0%) MES guards \n", - "\n", - " [............ ]\n", - " [......................... ]\n", - " [..................................... ]\n", - " [..................................................]\n", - " Found 0 / 4 ( 0.0%) !NDS transitions \n", - "\n", - " [......................... ]\n", - " Found 0 / 2 ( 0.0%) !DNA transitions \n", - "\n", - " [......................... ]\n", - " [..................................................]\n", - " [..................................................]\n", - " Found 2 / 2 (100.0%) Commuting actions \n", - "Generating guard dependency matrices done (0.0 sec)\n", - "\n", - "Written C code to /home/adl/git/spot/tests/python/tmpmmk02hmw.pml.spins.c\n", - "Compiled C code to PINS library tmpmmk02hmw.pml.spins\n", - "\n" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Yes, the `spins` compiler is quite verbose. Printing the resulting `model` object will show information about the variables in that model. " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "model" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "ltsmin model with the following variables:\n", - " P_0._pc: pc\n", - " P_0.a: int\n", - " P_0.b: int" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To instantiate a Kripke structure, one should provide a list of atomic proposition to observe." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "k = model.kripke(['P_0.a < 2', 'P_0.b > 1']); k" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "P_0._pc=0, P_0.a=0, P_0.b=0\n", - ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "P_0._pc=0, P_0.a=1, P_0.b=0\n", - ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "P_0._pc=0, P_0.a=0, P_0.b=1\n", - ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "P_0._pc=0, P_0.a=2, P_0.b=0\n", - "!"P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "P_0._pc=0, P_0.a=1, P_0.b=1\n", - ""P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "P_0._pc=0, P_0.a=0, P_0.b=2\n", - ""P_0.a < 2" & "P_0.b > 1" & !dead\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "\n", - "\n", - "6\n", - "\n", - "P_0._pc=0, P_0.a=3, P_0.b=0\n", - "!"P_0.a < 2" & !"P_0.b > 1" & dead\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "\n", - "\n", - "7\n", - "\n", - "P_0._pc=0, P_0.a=2, P_0.b=1\n", - "!"P_0.a < 2" & !"P_0.b > 1" & !dead\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "\n", - "\n", - "8\n", - "\n", - "P_0._pc=0, P_0.a=1, P_0.b=2\n", - ""P_0.a < 2" & "P_0.b > 1" & !dead\n", - "\n", - "\n", - "4->8\n", - "\n", - "\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "\n", - "\n", - "9\n", - "\n", - "P_0._pc=0, P_0.a=0, P_0.b=3\n", - ""P_0.a < 2" & "P_0.b > 1" & dead\n", - "\n", - "\n", - "5->9\n", - "\n", - "\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "\n", - "\n", - "10\n", - "\n", - "P_0._pc=0, P_0.a=3, P_0.b=1\n", - "!"P_0.a < 2" & !"P_0.b > 1" & dead\n", - "\n", - "\n", - "7->10\n", - "\n", - "\n", - "\n", - "\n", - "11\n", - "\n", - "P_0._pc=0, P_0.a=2, P_0.b=2\n", - "!"P_0.a < 2" & "P_0.b > 1" & !dead\n", - "\n", - "\n", - "7->11\n", - "\n", - "\n", - "\n", - "\n", - "8->11\n", - "\n", - "\n", - "\n", - "\n", - "12\n", - "\n", - "P_0._pc=0, P_0.a=1, P_0.b=3\n", - ""P_0.a < 2" & "P_0.b > 1" & dead\n", - "\n", - "\n", - "8->12\n", - "\n", - "\n", - "\n", - "\n", - "9->9\n", - "\n", - "\n", - "\n", - "\n", - "10->10\n", - "\n", - "\n", - "\n", - "\n", - "13\n", - "\n", - "P_0._pc=0, P_0.a=3, P_0.b=2\n", - "!"P_0.a < 2" & "P_0.b > 1" & dead\n", - "\n", - "\n", - "11->13\n", - "\n", - "\n", - "\n", - "\n", - "14\n", - "\n", - "P_0._pc=0, P_0.a=2, P_0.b=3\n", - "!"P_0.a < 2" & "P_0.b > 1" & dead\n", - "\n", - "\n", - "11->14\n", - "\n", - "\n", - "\n", - "\n", - "12->12\n", - "\n", - "\n", - "\n", - "\n", - "13->13\n", - "\n", - "\n", - "\n", - "\n", - "14->14\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fe0808e0240> >" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And then from this Kripke structure you can do some model checking using the same functions as illustrated in `ltsmin-dve.ipynb`.\n", - "\n", - "Loading from a `*.pml` file\n", - "---------------------------\n", - "\n", - "Another option is to use `ltsmin.load()` to load a Promela file directly. In order for this test-case to be self-contained, we are going to write the Promela file first, but in practice you probably already have your model." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!rm -rf test1.pml" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%%file test1.pml\n", - "active proctype P() {\n", - "int a = 0;\n", - "int b = 0;\n", - "x: if\n", - " :: d_step {a < 3 && b < 3; a = a + 1; } goto x;\n", - " :: d_step {a < 3 && b < 3; b = b + 1; } goto x;\n", - "fi;\n", - "}" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Writing test1.pml\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now load it:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "model2 = spot.ltsmin.load('test1.pml')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "model2" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "ltsmin model with the following variables:\n", - " P_0._pc: pc\n", - " P_0.a: int\n", - " P_0.b: int" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "!rm -f test1.pml test1.pml.spins.c test1.pml.spins" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 9 - } - ], - "metadata": {} } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/python/parity.ipynb b/tests/python/parity.ipynb index 1fe189586..f8bf6c652 100644 --- a/tests/python/parity.ipynb +++ b/tests/python/parity.ipynb @@ -1,4 +1,1952 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Definitions and examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In Spot a **Parity acceptance** is defined by an **kind**, a **style** and a **numsets** (number of acceptance sets):\n", + "+ The **numsets** is the number of acceptance sets used by the parity acceptance.\n", + "+ The **kind** can be either **max** or **min**. The parity kind is well defined only if the **numsets** is strictly greater than 1.\n", + " - **max** odd 4: *Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))*\n", + " - **min** odd 4: *Fin(0) & (Inf(1) | (Fin(2) & Inf(3)))*\n", + "+ The **style** can be either **odd** or **even**. The parity style is well defined only if the **numsets** is non-null.\n", + " - max **odd** 4: *Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))*\n", + " - min **even** 4: *Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))*\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Some parity acceptance examples:**\n", + "
\n", + "**numsets = 1:** \n", + "
\n", + "\n", + "| | **max** | **min** |\n", + "|:---------:|:--------------:|:--------------:|\n", + "| **odd** | Fin(1) | Fin(1) | \n", + "| **even** | Inf(0) | Inf(0) |\n", + "\n", + "
\n", + "
\n", + "**numsets = 2:** \n", + "
\n", + "\n", + "| | **max** | **min** |\n", + "|:---------:|:--------------------:|:--------------------:|\n", + "| **odd** | Inf(1) | Fin(0) | Fin(1) & Inf(0) | \n", + "| **even** | Fin(0) & Inf(1) | Inf(0) | Fin(1) |\n", + "\n", + "\n", + "
\n", + "
\n", + "**numsets = 3:** \n", + "
\n", + " \n", + "| | **max** | **min** |\n", + "|:---------:|:-------------------------------:|:-------------------------------:|\n", + "| **odd** | Fin(2) & (Inf(1) | Fin(0)) | Inf(2) | (Fin(1) & Inf(0)) | \n", + "| **even** | Fin(0) & (Inf(1) | Fin(2)) | Inf(0) | (Fin(1) & Inf(2)) |\n", + "\n", + "
\n", + "
\n", + "**numsets = 4:** \n", + "
\n", + "\n", + "| | **max** | **min** |\n", + "|:---------:|:-----------------------------------------------:|:-----------------------------------------------:|\n", + "| **odd** | Inf(3) | (Fin(2) & (Inf(1) | Fin(0))) | Fin(3) & (Inf(2) | (Fin(1) & Inf(0))) | \n", + "| **even** | Fin(0) & (Inf(1) | (Fin(2) & Inf(3))) | Inf(0) | (Fin(1) & (Inf(2) | Fin(3))) |\n", + "\n", + "
\n", + "According to the given examples, we can remark that:\n", + "+ Given a parity **max**: Acceptance sets with greater indexes are more significant\n", + "+ Given a parity **min**: Acceptance sets with lower indexes are more significant" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Change parity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## To toggle **style**\n", + "### A new acceptance set is introduced and all the existing sets' indexes are increased by 1.\n", + "#### Parity max odd 5 -> Parity max even\n", + "If the acceptance is a parity **max**, all the transitions that do not belong to any acceptance set will belong to the new set." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity max odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd5 = tuple(spot.automata(\"randaut -A 'parity max odd 5' -Q4 2|\"))[0]\n", + "display(aut_max_odd5.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new indexes of the acceptance sets:\n", + "+ 4 -> 5\n", + "+ 3 -> 4\n", + "+ 2 -> 3\n", + "+ 1 -> 2\n", + "+ 0 -> 1\n", + "+ ∅ -> 0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Result of Parity max odd 5 -> Parity max even 6" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")))))\n", + "[parity max even 6]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd5_to_even = spot.change_parity(aut_max_odd5, spot.parity_kind_any, spot.parity_style_even)\n", + "display(aut_max_odd5_to_even.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Parity min odd 5 -> Parity min even\n", + "If the acceptance is a parity **min**, the new acceptance set will not be used." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity min odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_min_odd5 = tuple(spot.automata(\"randaut -A 'parity min odd 5' -Q4 2|\"))[0]\n", + "display(aut_min_odd5.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new indexes of the acceptance sets:\n", + "+ 4 -> 5\n", + "+ 3 -> 4\n", + "+ 2 -> 3\n", + "+ 1 -> 2\n", + "+ 0 -> 1\n", + "+ ∅ -> ∅" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Result of Parity min odd 5 -> Parity min even 6" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))))\n", + "[parity min even 6]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_min_odd5_to_even = spot.change_parity(aut_min_odd5, spot.parity_kind_any, spot.parity_style_even)\n", + "display(aut_min_odd5_to_even.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### To toggle **kind**\n", + "#### The indexes of the acceptance sets are reversed\n", + "#### Parity max odd 5 ----> Parity min:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity max odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd5 = tuple(spot.automata(\"randaut -A 'parity max odd 5' -Q4 2|\"))[0]\n", + "display(aut_max_odd5.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new indexes of the acceptance sets:\n", + "+ 4 -> 0\n", + "+ 3 -> 1\n", + "+ 2 -> 2\n", + "+ 1 -> 3\n", + "+ 0 -> 4\n", + "+ ∅ -> ∅" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Result of Parity max odd 5 ----> Parity min odd 5:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity min odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd5_to_min = spot.change_parity(aut_max_odd5, spot.parity_kind_min, spot.parity_style_any)\n", + "display(aut_max_odd5_to_min.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Parity max odd 4 ----> Parity min odd:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "[parity max odd 4]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4 = tuple(spot.automata(\"randaut -A 'parity max odd 4' -Q4 2|\"))[0]\n", + "display(aut_max_odd4.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new indexes of the acceptance sets:\n", + "+ 3 -> 0\n", + "+ 2 -> 1\n", + "+ 1 -> 2\n", + "+ 0 -> 3\n", + "+ ∅ -> ∅" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Result of Parity max odd 4 ----> Parity min even 4:\n", + "\n", + "If the **numsets** is even and the **kind** is toggled, then the **style** will be toggled too." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "[parity min even 4]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4_to_min = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_any)\n", + "display(aut_max_odd4_to_min.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To keep the same **style** a new acceptance set is introduced, thus the **style** is toggled once again.\n", + "
\n", + "The new indexes of the acceptance sets are:\n", + "\n", + "+ 3 -> 0 -> 1\n", + "+ 2 -> 1 -> 2\n", + "+ 1 -> 2 -> 3\n", + "+ 0 -> 3 -> 4\n", + "+ ∅ -> ∅ -> 0 (as the resulting automaton is a parity min)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Result of Parity max odd 4 ----> Parity min even 5:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity min odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4_to_min_bis = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_same)\n", + "display(aut_max_odd4_to_min_bis.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Colorize parity\n", + "An automaton with a parity acceptance is not necessarily a parity automaton. It must be colored to be qualified like this.\n", + "## Parity max\n", + "Transitions with multiple acceptance sets are purified by keeping only the set with the greatest index.\n", + "
\n", + "If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.\n", + "
\n", + "The least significant place of a parity max acceptance is where the indexes are the lowest, so all the existing acceptance sets' indexes will be shifted.\n", + "#### Colorize parity max odd 4" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "[parity max odd 4]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4 = tuple(spot.automata(\"randaut -A 'parity max odd 4' -Q4 2|\"))[0]\n", + "display(aut_max_odd4.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new acceptance sets are:\n", + "+ ∅ -> 0\n", + "+ 0 -> 1\n", + "+ 1 -> 2\n", + "+ 2 -> 3\n", + "+ 3 -> 4\n", + "\n", + "#### The result of colorizing the given parity max odd 4 is" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))))\n", + "[parity max even 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4_colored = spot.colorize_parity(aut_max_odd4, False)\n", + "display(aut_max_odd4_colored.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can notice that the **style** has been toggled.\n", + "
\n", + "To prevent colorize_parity from this we can add one extra acceptance set in the acceptance condition.\n", + "\n", + "The new acceptance sets are now:\n", + "+ ∅ -> 1\n", + "+ 0 -> 2\n", + "+ 1 -> 3\n", + "+ 2 -> 4\n", + "+ 3 -> 5\n", + "#### The result of colorizing the given parity max odd 4 without changing the style is" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))))\n", + "[parity max odd 6]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_max_odd4_colored_bis = spot.colorize_parity(aut_max_odd4, True)\n", + "display(aut_max_odd4_colored_bis.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Parity min\n", + "Transitions with multiple acceptance sets are purified by keeping only the set with the lowest index.\n", + "
\n", + "If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.\n", + "
\n", + "The least significant place of a parity min acceptance is where the indexes are the greatest.\n", + "#### Colorize parity min odd 4" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")))\n", + "[parity min odd 4]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_min_odd4 = tuple(spot.automata(\"randaut -A 'parity min odd 4' -Q4 2|\"))[0]\n", + "display(aut_min_odd4.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The new acceptance sets are:\n", + "+ ∅ -> 4\n", + "+ 0 -> 0\n", + "+ 1 -> 1\n", + "+ 2 -> 2\n", + "+ 3 -> 3\n", + "\n", + "#### The result of colorizing the given parity max odd 4 is" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))))\n", + "[parity min odd 5]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut_min_odd4_colored_bis = spot.colorize_parity(aut_min_odd4, True)\n", + "display(aut_min_odd4_colored_bis.show(\".a\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Remark: colorizing a parity min won't change the **style** of the acceptance." + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,1941 +1964,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display\n", - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "heading", - "level": 1, - "metadata": {}, - "source": [ - "Definitions and examples" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In Spot a **Parity acceptance** is defined by an **kind**, a **style** and a **numsets** (number of acceptance sets):\n", - "+ The **numsets** is the number of acceptance sets used by the parity acceptance.\n", - "+ The **kind** can be either **max** or **min**. The parity kind is well defined only if the **numsets** is strictly greater than 1.\n", - " - **max** odd 4: *Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))*\n", - " - **min** odd 4: *Fin(0) & (Inf(1) | (Fin(2) & Inf(3)))*\n", - "+ The **style** can be either **odd** or **even**. The parity style is well defined only if the **numsets** is non-null.\n", - " - max **odd** 4: *Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))*\n", - " - min **even** 4: *Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))*\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Some parity acceptance examples:**\n", - "
\n", - "**numsets = 1:** \n", - "
\n", - "\n", - "| | **max** | **min** |\n", - "|:---------:|:--------------:|:--------------:|\n", - "| **odd** | Fin(1) | Fin(1) | \n", - "| **even** | Inf(0) | Inf(0) |\n", - "\n", - "
\n", - "
\n", - "**numsets = 2:** \n", - "
\n", - "\n", - "| | **max** | **min** |\n", - "|:---------:|:--------------------:|:--------------------:|\n", - "| **odd** | Inf(1) | Fin(0) | Fin(1) & Inf(0) | \n", - "| **even** | Fin(0) & Inf(1) | Inf(0) | Fin(1) |\n", - "\n", - "\n", - "
\n", - "
\n", - "**numsets = 3:** \n", - "
\n", - " \n", - "| | **max** | **min** |\n", - "|:---------:|:-------------------------------:|:-------------------------------:|\n", - "| **odd** | Fin(2) & (Inf(1) | Fin(0)) | Inf(2) | (Fin(1) & Inf(0)) | \n", - "| **even** | Fin(0) & (Inf(1) | Fin(2)) | Inf(0) | (Fin(1) & Inf(2)) |\n", - "\n", - "
\n", - "
\n", - "**numsets = 4:** \n", - "
\n", - "\n", - "| | **max** | **min** |\n", - "|:---------:|:-----------------------------------------------:|:-----------------------------------------------:|\n", - "| **odd** | Inf(3) | (Fin(2) & (Inf(1) | Fin(0))) | Fin(3) & (Inf(2) | (Fin(1) & Inf(0))) | \n", - "| **even** | Fin(0) & (Inf(1) | (Fin(2) & Inf(3))) | Inf(0) | (Fin(1) & (Inf(2) | Fin(3))) |\n", - "\n", - "
\n", - "According to the given examples, we can remark that:\n", - "+ Given a parity **max**: Acceptance sets with greater indexes are more significant\n", - "+ Given a parity **min**: Acceptance sets with lower indexes are more significant" - ] - }, - { - "cell_type": "heading", - "level": 1, - "metadata": {}, - "source": [ - "Change parity" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## To toggle **style**\n", - "### A new acceptance set is introduced and all the existing sets' indexes are increased by 1.\n", - "#### Parity max odd 5 -> Parity max even\n", - "If the acceptance is a parity **max**, all the transitions that do not belong to any acceptance set will belong to the new set." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd5 = tuple(spot.automata(\"randaut -A 'parity max odd 5' -Q4 2|\"))[0]\n", - "display(aut_max_odd5.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u2779\n", - ") & (Inf(\n", - "\u2778\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2776\n", - ") | Fin(\n", - "\u24ff\n", - "))))\n", - "[parity max odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new indexes of the acceptance sets:\n", - "+ 4 -> 5\n", - "+ 3 -> 4\n", - "+ 2 -> 3\n", - "+ 1 -> 2\n", - "+ 0 -> 1\n", - "+ \u2205 -> 0" - ] - }, - { - "cell_type": "heading", - "level": 4, - "metadata": {}, - "source": [ - "Result of Parity max odd 5 -> Parity max even 6" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd5_to_even = spot.change_parity(aut_max_odd5, spot.parity_kind_any, spot.parity_style_even)\n", - "display(aut_max_odd5_to_even.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u277a\n", - ") & (Inf(\n", - "\u2779\n", - ") | (Fin(\n", - "\u2778\n", - ") & (Inf(\n", - "\u2777\n", - ") | (Fin(\n", - "\u2776\n", - ") & Inf(\n", - "\u24ff\n", - ")))))\n", - "[parity max even 6]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u277a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u277a\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Parity min odd 5 -> Parity min even\n", - "If the acceptance is a parity **min**, the new acceptance set will not be used." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_min_odd5 = tuple(spot.automata(\"randaut -A 'parity min odd 5' -Q4 2|\"))[0]\n", - "display(aut_min_odd5.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2778\n", - ") | Fin(\n", - "\u2779\n", - "))))\n", - "[parity min odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new indexes of the acceptance sets:\n", - "+ 4 -> 5\n", - "+ 3 -> 4\n", - "+ 2 -> 3\n", - "+ 1 -> 2\n", - "+ 0 -> 1\n", - "+ \u2205 -> \u2205" - ] - }, - { - "cell_type": "heading", - "level": 4, - "metadata": {}, - "source": [ - "Result of Parity min odd 5 -> Parity min even 6" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_min_odd5_to_even = spot.change_parity(aut_min_odd5, spot.parity_kind_any, spot.parity_style_even)\n", - "display(aut_min_odd5_to_even.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | (Fin(\n", - "\u2776\n", - ") & (Inf(\n", - "\u2777\n", - ") | (Fin(\n", - "\u2778\n", - ") & (Inf(\n", - "\u2779\n", - ") | Fin(\n", - "\u277a\n", - ")))))\n", - "[parity min even 6]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u277a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u277a\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### To toggle **kind**\n", - "#### The indexes of the acceptance sets are reversed\n", - "#### Parity max odd 5 ----> Parity min:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd5 = tuple(spot.automata(\"randaut -A 'parity max odd 5' -Q4 2|\"))[0]\n", - "display(aut_max_odd5.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u2779\n", - ") & (Inf(\n", - "\u2778\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2776\n", - ") | Fin(\n", - "\u24ff\n", - "))))\n", - "[parity max odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new indexes of the acceptance sets:\n", - "+ 4 -> 0\n", - "+ 3 -> 1\n", - "+ 2 -> 2\n", - "+ 1 -> 3\n", - "+ 0 -> 4\n", - "+ \u2205 -> \u2205" - ] - }, - { - "cell_type": "heading", - "level": 4, - "metadata": {}, - "source": [ - "Result of Parity max odd 5 ----> Parity min odd 5:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd5_to_min = spot.change_parity(aut_max_odd5, spot.parity_kind_min, spot.parity_style_any)\n", - "display(aut_max_odd5_to_min.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2778\n", - ") | Fin(\n", - "\u2779\n", - "))))\n", - "[parity min odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "heading", - "level": 4, - "metadata": {}, - "source": [ - "Parity max odd 4 ----> Parity min odd:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4 = tuple(spot.automata(\"randaut -A 'parity max odd 4' -Q4 2|\"))[0]\n", - "display(aut_max_odd4.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2778\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2776\n", - ") | Fin(\n", - "\u24ff\n", - ")))\n", - "[parity max odd 4]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new indexes of the acceptance sets:\n", - "+ 3 -> 0\n", - "+ 2 -> 1\n", - "+ 1 -> 2\n", - "+ 0 -> 3\n", - "+ \u2205 -> \u2205" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Result of Parity max odd 4 ----> Parity min even 4:\n", - "\n", - "If the **numsets** is even and the **kind** is toggled, then the **style** will be toggled too." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4_to_min = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_any)\n", - "display(aut_max_odd4_to_min.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | (Fin(\n", - "\u2776\n", - ") & (Inf(\n", - "\u2777\n", - ") | Fin(\n", - "\u2778\n", - ")))\n", - "[parity min even 4]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To keep the same **style** a new acceptance set is introduced, thus the **style** is toggled once again.\n", - "
\n", - "The new indexes of the acceptance sets are:\n", - "\n", - "+ 3 -> 0 -> 1\n", - "+ 2 -> 1 -> 2\n", - "+ 1 -> 2 -> 3\n", - "+ 0 -> 3 -> 4\n", - "+ \u2205 -> \u2205 -> 0 (as the resulting automaton is a parity min)" - ] - }, - { - "cell_type": "heading", - "level": 4, - "metadata": {}, - "source": [ - "Result of Parity max odd 4 ----> Parity min even 5:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4_to_min_bis = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_same)\n", - "display(aut_max_odd4_to_min_bis.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2778\n", - ") | Fin(\n", - "\u2779\n", - "))))\n", - "[parity min odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Colorize parity\n", - "An automaton with a parity acceptance is not necessarily a parity automaton. It must be colored to be qualified like this.\n", - "## Parity max\n", - "Transitions with multiple acceptance sets are purified by keeping only the set with the greatest index.\n", - "
\n", - "If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.\n", - "
\n", - "The least significant place of a parity max acceptance is where the indexes are the lowest, so all the existing acceptance sets' indexes will be shifted.\n", - "#### Colorize parity max odd 4" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4 = tuple(spot.automata(\"randaut -A 'parity max odd 4' -Q4 2|\"))[0]\n", - "display(aut_max_odd4.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2778\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2776\n", - ") | Fin(\n", - "\u24ff\n", - ")))\n", - "[parity max odd 4]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new acceptance sets are:\n", - "+ \u2205 -> 0\n", - "+ 0 -> 1\n", - "+ 1 -> 2\n", - "+ 2 -> 3\n", - "+ 3 -> 4\n", - "\n", - "#### The result of colorizing the given parity max odd 4 is" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4_colored = spot.colorize_parity(aut_max_odd4, False)\n", - "display(aut_max_odd4_colored.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2779\n", - ") | (Fin(\n", - "\u2778\n", - ") & (Inf(\n", - "\u2777\n", - ") | (Fin(\n", - "\u2776\n", - ") & Inf(\n", - "\u24ff\n", - "))))\n", - "[parity max even 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can notice that the **style** has been toggled.\n", - "
\n", - "To prevent colorize_parity from this we can add one extra acceptance set in the acceptance condition.\n", - "\n", - "The new acceptance sets are now:\n", - "+ \u2205 -> 1\n", - "+ 0 -> 2\n", - "+ 1 -> 3\n", - "+ 2 -> 4\n", - "+ 3 -> 5\n", - "#### The result of colorizing the given parity max odd 4 without changing the style is" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_max_odd4_colored_bis = spot.colorize_parity(aut_max_odd4, True)\n", - "display(aut_max_odd4_colored_bis.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u277a\n", - ") | (Fin(\n", - "\u2779\n", - ") & (Inf(\n", - "\u2778\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2776\n", - ") | Fin(\n", - "\u24ff\n", - ")))))\n", - "[parity max odd 6]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Parity min\n", - "Transitions with multiple acceptance sets are purified by keeping only the set with the lowest index.\n", - "
\n", - "If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.\n", - "
\n", - "The least significant place of a parity min acceptance is where the indexes are the greatest.\n", - "#### Colorize parity min odd 4" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_min_odd4 = tuple(spot.automata(\"randaut -A 'parity min odd 4' -Q4 2|\"))[0]\n", - "display(aut_min_odd4.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2778\n", - ")))\n", - "[parity min odd 4]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The new acceptance sets are:\n", - "+ \u2205 -> 4\n", - "+ 0 -> 0\n", - "+ 1 -> 1\n", - "+ 2 -> 2\n", - "+ 3 -> 3\n", - "\n", - "#### The result of colorizing the given parity max odd 4 is" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut_min_odd4_colored_bis = spot.colorize_parity(aut_min_odd4, True)\n", - "display(aut_min_odd4_colored_bis.show(\".a\"))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & (Inf(\n", - "\u2778\n", - ") | Fin(\n", - "\u2779\n", - "))))\n", - "[parity min odd 5]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2779\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2779\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Remark: colorizing a parity min won't change the **style** of the acceptance." - ] - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/piperead.ipynb b/tests/python/piperead.ipynb index 8859d5f57..6e9b6db75 100644 --- a/tests/python/piperead.ipynb +++ b/tests/python/piperead.ipynb @@ -1,4 +1,480 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display \n", + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reading automata output from processes\n", + "\n", + "If an argument of `spot.automata` ends with `|`, then it is interpreted as a shell command that outputs one automaton or more." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd0404bab0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd004afa50> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd004afae0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd004afa80> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for a in spot.automata('ltl2tgba -s \"a U b\"; ltl2tgba --lbtt \"b\"|', 'ltl2tgba -H \"GFa\" \"a & GFb\"|'):\n", + " display(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A single automaton can be read using `spot.automaton()`, with the same convention." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd004afa20> >" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.automaton('ltl2tgba -s6 \"a U b\"|')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Error handling\n", + "\n", + "If the shell command terminates with a non-zero exit status, we should get an exception." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "CalledProcessError", + "evalue": "Command 'non-existing-command' returned non-zero exit status 127.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'non-existing-command|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 479\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 480\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 481\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 482\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 483\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 464\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 466\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 467\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 468\u001b[0m \u001b[0;31m# reporting the following error: \"\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fbd004af8d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "CalledProcessError", + "evalue": "Command 'ltl2tgba \"syntax U U error\"' returned non-zero exit status 2.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ltl2tgba 'a U b'|\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'ltl2tgba \"syntax U U error\"|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 464\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 466\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 467\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 468\u001b[0m \u001b[0;31m# reporting the following error: \" 481\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 482\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mStopIteration\u001b[0m: ", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'true|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 481\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 482\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 483\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 484\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 485\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRuntimeError\u001b[0m: Failed to read automaton from true|" + ] + } + ], + "source": [ + "spot.automaton('true|')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -15,500 +491,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display \n", - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Reading automata output from processes\n", - "\n", - "If an argument of `spot.automata` ends with `|`, then it is interpreted as a shell command that outputs one automaton or more." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for a in spot.automata('ltl2tgba -s \"a U b\"; ltl2tgba --lbtt \"b\"|', 'ltl2tgba -H \"GFa\" \"a & GFb\"|'):\n", - " display(a)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d270> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d450> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d270> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d120> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A single automaton can be read using `spot.automaton()`, with the same convention." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('ltl2tgba -s6 \"a U b\"|')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d1b0> >" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Error handling\n", - "\n", - "If the shell command terminates with a non-zero exit status, we should get an exception." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.automaton('non-existing-command|')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "CalledProcessError", - "evalue": "Command 'non-existing-command' returned non-zero exit status 127", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'non-existing-command|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 463\u001b[0m See `spot.automata` for a list of supported formats.\"\"\"\n\u001b[1;32m 464\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 465\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 466\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 467\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 448\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 449\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 450\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 451\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 452\u001b[0m \u001b[0;31m# reporting the following error: \"\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f549852d360> >" - ] - }, - { - "ename": "CalledProcessError", - "evalue": "Command 'ltl2tgba \"syntax U U error\"' returned non-zero exit status 2", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ltl2tgba 'a U b'|\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'ltl2tgba \"syntax U U error\"|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomata\u001b[0;34m(timeout, ignore_abort, trust_hoa, no_sid, debug, *sources)\u001b[0m\n\u001b[1;32m 448\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mproc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 449\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 450\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0msubprocess\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 451\u001b[0m \u001b[0;31m# deleting o explicitely now prevents Python 3.5 from\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 452\u001b[0m \u001b[0;31m# reporting the following error: \" 465\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 466\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mStopIteration\u001b[0m: ", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mspot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautomaton\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'true|'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/__init__.py\u001b[0m in \u001b[0;36mautomaton\u001b[0;34m(filename, **kwargs)\u001b[0m\n\u001b[1;32m 465\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mautomata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 466\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 467\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Failed to read automaton from {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 468\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 469\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mRuntimeError\u001b[0m: Failed to read automaton from true|" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": true, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": null - } - ], - "metadata": {} + "version": "3.6.4" } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/product.ipynb b/tests/python/product.ipynb index 774439a00..05c583bfd 100644 --- a/tests/python/product.ipynb +++ b/tests/python/product.ipynb @@ -1,4 +1,2300 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "import spot\n", + "import buddy\n", + "spot.setup(show_default='.tavb')\n", + "\n", + "def horiz(*args):\n", + " \"\"\"Display multiple arguments side by side in a table.\"\"\"\n", + " s = ''\n", + " for arg in args:\n", + " s += ''\n", + " return HTML(s + '
' + arg.data + '
')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Anatomy of a product\n", + "\n", + "In this notebook, we write a Python function that constructs the product of two automata.\n", + "\n", + "This is obviously not a new feature: Spot can already make a product of two automata using its `product()` function. \n", + "For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 3]\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "2,0\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "2,1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a1 = spot.translate('X(a W b)')\n", + "a2 = spot.translate('G(Fc U b)')\n", + "prod = spot.product(a1, a2)\n", + "horiz(a1.show(), a2.show(), prod.show())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The builtin `spot.product()` function produces an automaton whose language is the intersection of the two input languages. It does so by building an automaton that keeps track of the runs in the two input automata. The states are labeled by pairs of input states so that we can more easily follow what is going on, but those labels are purely cosmetic. The acceptance condition is the conjunction of the two acceptance condition, but the acceptance sets of one input automaton have been shifted to not conflict with the other automaton.\n", + "\n", + "In fact, that automaton printer has an option to shift those sets in its output, and this is perfect for illustrating products. For instance `a.show('+3')` will display `a1` with all its acceptance sets shifted by 3. \n", + "\n", + "Let's define a function for displaying the three automata involved in a product, using this shift option so we can follow what is going on with the acceptance sets." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 3]\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "2,0\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "2,1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def show_prod(a1, a2, res):\n", + " s1 = a1.num_sets()\n", + " display(horiz(a1.show(), a2.show('.tavb+{}'.format(s1)), res.show()))\n", + "\n", + "show_prod(a1, a2, prod)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Building a product\n", + "\n", + "Let's now rewrite `product()` in Python. We will do that in three steps.\n", + "\n", + "\n", + "## First attempt\n", + "\n", + "First, we build a product without taking care of the acceptance sets. We just want to get the general shape of the algorithm.\n", + "\n", + "We will build an automaton of type `twa_graph`, i.e., an automaton represented explicitely using a graph. In those automata, states are numbered by integers, starting from `0`. (Those states can also be given a different name, which is why the the `product()` shows us something that appears to be labeled by pairs, but the real identifier of each state is an integer.)\n", + "\n", + "We will use a dictionary to keep track of the association between a pair `(ls,rs)` of input states, and its number in the output." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def product1(left, right):\n", + " # A bdd_dict object associates BDD variables (that are \n", + " # used in BDDs labeleing the edges) to atomic propositions.\n", + " bdict = left.get_dict()\n", + " # If the two automata do not have the same BDD dict, then\n", + " # we cannot easily detect compatible transitions.\n", + " if right.get_dict() != bdict:\n", + " raise RuntimeError(\"automata should share their dictionary\")\n", + " \n", + " result = spot.make_twa_graph(bdict)\n", + " # This will be our state dictionary\n", + " sdict = {}\n", + " # The list of output states for which we have not yet\n", + " # computed the successors. Items on this list are triplets\n", + " # of the form (ls, rs, p) where ls,rs are the state number in\n", + " # the left and right automata, and p is the state number if\n", + " # the output automaton.\n", + " todo = []\n", + " # Transform a pair of state number (ls, rs) into a state number in\n", + " # the output automaton, creating a new state if needed. Whenever\n", + " # a new state is created, we can add it to todo.\n", + " def dst(ls, rs):\n", + " pair = (ls, rs)\n", + " p = sdict.get(pair)\n", + " if p is None:\n", + " p = result.new_state()\n", + " sdict[pair] = p\n", + " todo.append((ls, rs, p))\n", + " return p\n", + " \n", + " # Setup the initial state. It always exists.\n", + " result.set_init_state(dst(left.get_init_state_number(), \n", + " right.get_init_state_number()))\n", + "\n", + " # Build all states and edges in the product\n", + " while todo:\n", + " lsrc, rsrc, osrc = todo.pop()\n", + " for lt in left.out(lsrc):\n", + " for rt in right.out(rsrc):\n", + " cond = lt.cond & rt.cond\n", + " if cond != buddy.bddfalse:\n", + " result.new_edge(osrc, dst(lt.dst, rt.dst), cond)\n", + " return result\n", + "\n", + "p1 = product1(a1, a2)\n", + "show_prod(a1, a2, p1)" + ] + }, + { + "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 propositions used by the result automaton. This as two consequences:\n", + "- calling `p1.ap()` will return an empty set of atomic propositions" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(a, b)\n", + "(c, b)\n", + "()\n" + ] + } + ], + "source": [ + "print(a1.ap())\n", + "print(a2.ap())\n", + "print(p1.ap())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- the `bdd_dict` instance that is shared by the three automata knows that the atomic propositions `a` and `b` are used by automata `a1` and that `b` and `c` are used by `a2`. But it is unaware of `p1`. That means that if we delete automata `a1` and `a2`, then the `bdd_dict` will release the associated BDD variables, and attempting to print automaton `p1` will either crash (because it uses bdd variables that are not associated to any atomic proposition) or display different atomic propositions (in case the BDD variables have been associated to different propositions in the meantime).\n", + "\n", + "These two issues are fixed by either calling `p1.register_ap(...)` for each atomic proposition, or in our case `p1.copy_ap_of(...)` to copy the atomic propositions of each input automaton. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Second attempt: a working product\n", + "\n", + "This fixes the list of atomtic propositions, as discussed above, and also sets the correct acceptance condition.\n", + "The `set_acceptance` method takes two arguments: a number of sets, and an acceptance function. In our case, both of these arguments are readily computed from the number of states and acceptance functions of the input automata." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(a, b, c)\n" + ] + } + ], + "source": [ + "def product2(left, right):\n", + " bdict = left.get_dict()\n", + " if right.get_dict() != bdict:\n", + " raise RuntimeError(\"automata should share their dictionary\")\n", + " \n", + " result = spot.make_twa_graph(bdict)\n", + " # Copy the atomic propositions of the two input automata\n", + " result.copy_ap_of(left)\n", + " result.copy_ap_of(right)\n", + " \n", + " sdict = {}\n", + " todo = []\n", + " def dst(ls, rs):\n", + " pair = (ls, rs)\n", + " p = sdict.get(pair)\n", + " if p is None:\n", + " p = result.new_state()\n", + " sdict[pair] = p\n", + " todo.append((ls, rs, p))\n", + " return p\n", + " \n", + " result.set_init_state(dst(left.get_init_state_number(), \n", + " right.get_init_state_number()))\n", + "\n", + " # The acceptance sets of the right automaton will be shifted by this amount\n", + " shift = left.num_sets()\n", + " result.set_acceptance(shift + right.num_sets(),\n", + " left.get_acceptance() & (right.get_acceptance() << shift))\n", + " \n", + " while todo:\n", + " lsrc, rsrc, osrc = todo.pop()\n", + " for lt in left.out(lsrc):\n", + " for rt in right.out(rsrc):\n", + " cond = lt.cond & rt.cond\n", + " if cond != buddy.bddfalse:\n", + " # membership of this transitions to the new acceptance sets\n", + " acc = lt.acc | (rt.acc << shift)\n", + " result.new_edge(osrc, dst(lt.dst, rt.dst), cond, acc)\n", + " return result\n", + "\n", + "p2 = product2(a1, a2)\n", + "show_prod(a1, a2, p2)\n", + "print(p2.ap())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Third attempt: a more usable product\n", + "\n", + "We could stop with the previous function: the result is a correct product from a theoretical point of view. However our function is still inferior to `spot.product()` in a couple of points:\n", + "- states are not presented as pairs\n", + "- the properties of the resulting automaton are not set\n", + "\n", + "The former point could be addressed by calling `set_state_names()` and passing an array of strings: if a state number is smaller than the size of that array, then the string at that position will be displayed instead of the state number in the dot output. However we can do even better by using `set_product_states()` and passing an array of pairs of states. Besides the output routines, some algorithms actually retrieve this vector of pair of states to work on the product.\n", + "\n", + "Regarding the latter point, consider for instance the deterministic nature of these automata. In Spot an automaton is deterministic if it is both existential (no universal branching) and universal (no non-deterministic branching). In our case we will restrict the algorithm to existantial input (by asserting `is_existential()` on both operands), so we can consider that the `prop_universal()` property is an indication of determinism:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "yes\n", + "yes\n", + "yes\n", + "maybe\n" + ] + } + ], + "source": [ + "print(a1.prop_universal())\n", + "print(a2.prop_universal())\n", + "print(prod.prop_universal())\n", + "print(p1.prop_universal())" + ] + }, + { + "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", + "\n", + " if left.prop_universal() and right.prop_universal():\n", + " result.prop_universal(True)\n", + " \n", + "at the end of our function. Note that this is **not** the same as\n", + "\n", + " result.prop_universal(left.prop_universal() and right.prop_universal())\n", + "\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_universal(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", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "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" + ] + } + ], + "source": [ + "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)))" + ] + }, + { + "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_universal() and right.prop_universal():\n", + " result.prop_universal(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." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 3]\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "2,0\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "2,1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "yes\n" + ] + } + ], + "source": [ + "def product3(left, right):\n", + " # the twa_graph.is_existential() method returns a Boolean, not a spot.trival\n", + " if not (left.is_existential() and right.is_existential()):\n", + " raise RuntimeError(\"alternating automata are not supported\")\n", + " bdict = left.get_dict()\n", + " if right.get_dict() != bdict:\n", + " raise RuntimeError(\"automata should share their dictionary\")\n", + " \n", + " result = spot.make_twa_graph(bdict)\n", + " result.copy_ap_of(left)\n", + " result.copy_ap_of(right)\n", + " \n", + " pairs = [] # our array of state pairs\n", + " sdict = {}\n", + " todo = []\n", + " def dst(ls, rs):\n", + " pair = (ls, rs)\n", + " p = sdict.get(pair)\n", + " if p is None:\n", + " p = result.new_state()\n", + " sdict[pair] = p\n", + " todo.append((ls, rs, p))\n", + " pairs.append((ls, rs)) # name each state\n", + " return p\n", + " \n", + " result.set_init_state(dst(left.get_init_state_number(), \n", + " right.get_init_state_number()))\n", + "\n", + " shift = left.num_sets()\n", + " result.set_acceptance(shift + right.num_sets(),\n", + " left.get_acceptance() & (right.get_acceptance() << shift))\n", + " \n", + " while todo:\n", + " lsrc, rsrc, osrc = todo.pop()\n", + " for lt in left.out(lsrc):\n", + " for rt in right.out(rsrc):\n", + " cond = lt.cond & rt.cond\n", + " if cond != buddy.bddfalse:\n", + " acc = lt.acc | (rt.acc << shift)\n", + " result.new_edge(osrc, dst(lt.dst, rt.dst), cond, acc)\n", + "\n", + " # Remember the origin of our states\n", + " result.set_product_states(pairs)\n", + " \n", + " # Loop over all the properties we want to preserve if they hold in both automata\n", + " for p in ('prop_universal', 'prop_complete', 'prop_weak', 'prop_inherently_weak', \n", + " 'prop_terminal', 'prop_stutter_invariant', 'prop_state_acc'):\n", + " if getattr(left, p)() and getattr(right, p)():\n", + " getattr(result, p)(True)\n", + " return result\n", + "\n", + "p3 = product3(a1, a2)\n", + "show_prod(a1, a2, p3)\n", + "print(p3.prop_universal())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For development, it is useful to know that we can force the automaton printer to show the real state numbers (not the pairs) by passing option `1`, and that we can retrieve the associated pairs ourselves." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "a & !b & c\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & !b & !c\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0: (1, 0)\n", + "1: (0, 0)\n", + "2: (0, 1)\n", + "3: (2, 0)\n", + "4: (2, 1)\n" + ] + } + ], + "source": [ + "display(p3.show('.1'))\n", + "pairs = p3.get_product_states()\n", + "for s in range(p3.num_states()):\n", + " print(\"{}: {}\".format(s, pairs[s]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Timings\n", + "\n", + "As an indication of how slow it is to implement such an algorithm using the Python bindings of Spot, consider the following comparison:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1000 loops, best of 3: 231 µs per loop\n" + ] + } + ], + "source": [ + "%timeit product3(a1, a2)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The slowest run took 5.96 times longer than the fastest. This could mean that an intermediate result is being cached.\n", + "100000 loops, best of 3: 4.6 µs per loop\n" + ] + } + ], + "source": [ + "%timeit spot.product(a1, a2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Depending on the machine where this notebook has been run, using the C++ version of the product can be 1 to 2 order of magnitude faster. This is due to all the type conversions (converting Python types to C++ types) that occurs everytime a function/method of Spot is called from Python. When calling high-level C++ functions (such as `spot.product()`) from Python, the overhead is negligible because most of the time is spent on the C++ side, actually executing the function. However when calling low-level functions (such as `new_edge()`, `new_state()`, `out()`) most of the time is spent converting the arguments from Python to C++ and the results from C++ to Python.\n", + "\n", + "Despite that speed difference, Python can be useful to prototype an algorithm before implementing it in C++." + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,2298 +2312,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display, HTML\n", - "import spot\n", - "import buddy\n", - "spot.setup(show_default='.tavb')\n", - "\n", - "def horiz(*args):\n", - " \"\"\"Display multiple arguments side by side in a table.\"\"\"\n", - " s = ''\n", - " for arg in args:\n", - " s += ''\n", - " return HTML(s + '
' + arg.data + '
')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Anatomy of a product\n", - "\n", - "In this notebook, we write a Python function that constructs the product of two automata.\n", - "\n", - "This is obviously not a new feature: Spot can already make a product of two automata using its `product()` function. \n", - "For instance:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a1 = spot.translate('X(a W b)')\n", - "a2 = spot.translate('G(Fc U b)')\n", - "prod = spot.product(a1, a2)\n", - "horiz(a1.show(), a2.show(), prod.show())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\u2776\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 3]\n", - "\n", - "\n", - "0\n", - "\n", - "1,0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "0,1\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "2,0\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "2,1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The builtin `spot.product()` function produces an automaton whose language is the intersection of the two input languages. It does so by building an automaton that keeps track of the runs in the two input automata. The states are labeled by pairs of input states so that we can more easily follow what is going on, but those labels are purely cosmetic. The acceptance condition is the conjunction of the two acceptance condition, but the acceptance sets of one input automaton have been shifted to not conflict with the other automaton.\n", - "\n", - "In fact, that automaton printer has an option to shift those sets in its output, and this is perfect for illustrating products. For instance `a.show('+3')` will display `a1` with all its acceptance sets shifted by 3. \n", - "\n", - "Let's define a function for displaying the three automata involved in a product, using this shift option so we can follow what is going on with the acceptance sets." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def show_prod(a1, a2, res):\n", - " s1 = a1.num_sets()\n", - " display(horiz(a1.show(), a2.show('.tavb+{}'.format(s1)), res.show()))\n", - "\n", - "show_prod(a1, a2, prod)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b & c\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\u2777\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 3]\n", - "\n", - "\n", - "0\n", - "\n", - "1,0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "0,1\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "2,0\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "2,1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Building a product\n", - "\n", - "Let's now rewrite `product()` in Python. We will do that in three steps.\n", - "\n", - "\n", - "## First attempt\n", - "\n", - "First, we build a product without taking care of the acceptance sets. We just want to get the general shape of the algorithm.\n", - "\n", - "We will build an automaton of type `twa_graph`, i.e., an automaton represented explicitely using a graph. In those automata, states are numbered by integers, starting from `0`. (Those states can also be given a different name, which is why the the `product()` shows us something that appears to be labeled by pairs, but the real identifier of each state is an integer.)\n", - "\n", - "We will use a dictionary to keep track of the association between a pair `(ls,rs)` of input states, and its number in the output." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def product1(left, right):\n", - " # A bdd_dict object associates BDD variables (that are \n", - " # used in BDDs labeleing the edges) to atomic propositions.\n", - " bdict = left.get_dict()\n", - " # If the two automata do not have the same BDD dict, then\n", - " # we cannot easily detect compatible transitions.\n", - " if right.get_dict() != bdict:\n", - " raise RuntimeError(\"automata should share their dictionary\")\n", - " \n", - " result = spot.make_twa_graph(bdict)\n", - " # This will be our state dictionary\n", - " sdict = {}\n", - " # The list of output states for which we have not yet\n", - " # computed the successors. Items on this list are triplets\n", - " # of the form (ls, rs, p) where ls,rs are the state number in\n", - " # the left and right automata, and p is the state number if\n", - " # the output automaton.\n", - " todo = []\n", - " # Transform a pair of state number (ls, rs) into a state number in\n", - " # the output automaton, creating a new state if needed. Whenever\n", - " # a new state is created, we can add it to todo.\n", - " def dst(ls, rs):\n", - " pair = (ls, rs)\n", - " p = sdict.get(pair)\n", - " if p is None:\n", - " p = result.new_state()\n", - " sdict[pair] = p\n", - " todo.append((ls, rs, p))\n", - " return p\n", - " \n", - " # Setup the initial state. It always exists.\n", - " result.set_init_state(dst(left.get_init_state_number(), \n", - " right.get_init_state_number()))\n", - "\n", - " # Build all states and edges in the product\n", - " while todo:\n", - " lsrc, rsrc, osrc = todo.pop()\n", - " for lt in left.out(lsrc):\n", - " for rt in right.out(rsrc):\n", - " cond = lt.cond & rt.cond\n", - " if cond != buddy.bddfalse:\n", - " result.new_edge(osrc, dst(lt.dst, rt.dst), cond)\n", - " return result\n", - "\n", - "p1 = product1(a1, a2)\n", - "show_prod(a1, a2, p1)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b & c\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\u2777\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "t\n", - "[all]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "" - ] - } - ], - "prompt_number": 4 - }, - { - "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 propositions used by the result automaton. This as two consequences:\n", - "- calling `p1.ap()` will return an empty set of atomic propositions" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(a1.ap())\n", - "print(a2.ap())\n", - "print(p1.ap())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(a, b)\n", - "(c, b)\n", - "()\n" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- the `bdd_dict` instance that is shared by the three automata knows that the atomic propositions `a` and `b` are used by automata `a1` and that `b` and `c` are used by `a2`. But it is unaware of `p1`. That means that if we delete automata `a1` and `a2`, then the `bdd_dict` will release the associated BDD variables, and attempting to print automaton `p1` will either crash (because it uses bdd variables that are not associated to any atomic proposition) or display different atomic propositions (in case the BDD variables have been associated to different propositions in the meantime).\n", - "\n", - "These two issues are fixed by either calling `p1.register_ap(...)` for each atomic proposition, or in our case `p1.copy_ap_of(...)` to copy the atomic propositions of each input automaton. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Second attempt: a working product\n", - "\n", - "This fixes the list of atomtic propositions, as discussed above, and also sets the correct acceptance condition.\n", - "The `set_acceptance` method takes two arguments: a number of sets, and an acceptance function. In our case, both of these arguments are readily computed from the number of states and acceptance functions of the input automata." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def product2(left, right):\n", - " bdict = left.get_dict()\n", - " if right.get_dict() != bdict:\n", - " raise RuntimeError(\"automata should share their dictionary\")\n", - " \n", - " result = spot.make_twa_graph(bdict)\n", - " # Copy the atomic propositions of the two input automata\n", - " result.copy_ap_of(left)\n", - " result.copy_ap_of(right)\n", - " \n", - " sdict = {}\n", - " todo = []\n", - " def dst(ls, rs):\n", - " pair = (ls, rs)\n", - " p = sdict.get(pair)\n", - " if p is None:\n", - " p = result.new_state()\n", - " sdict[pair] = p\n", - " todo.append((ls, rs, p))\n", - " return p\n", - " \n", - " result.set_init_state(dst(left.get_init_state_number(), \n", - " right.get_init_state_number()))\n", - "\n", - " # The acceptance sets of the right automaton will be shifted by this amount\n", - " shift = left.num_sets()\n", - " result.set_acceptance(shift + right.num_sets(),\n", - " left.get_acceptance() & (right.get_acceptance() << shift))\n", - " \n", - " while todo:\n", - " lsrc, rsrc, osrc = todo.pop()\n", - " for lt in left.out(lsrc):\n", - " for rt in right.out(rsrc):\n", - " cond = lt.cond & rt.cond\n", - " if cond != buddy.bddfalse:\n", - " # membership of this transitions to the new acceptance sets\n", - " acc = lt.acc | (rt.acc << shift)\n", - " result.new_edge(osrc, dst(lt.dst, rt.dst), cond, acc)\n", - " return result\n", - "\n", - "p2 = product2(a1, a2)\n", - "show_prod(a1, a2, p2)\n", - "print(p2.ap())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b & c\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\u2777\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(a, b, c)\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Third attempt: a more usable product\n", - "\n", - "We could stop with the previous function: the result is a correct product from a theoretical point of view. However our function is still inferior to `spot.product()` in a couple of points:\n", - "- states are not presented as pairs\n", - "- the properties of the resulting automaton are not set\n", - "\n", - "The former point could be addressed by calling `set_state_names()` and passing an array of strings: if a state number is smaller than the size of that array, then the string at that position will be displayed instead of the state number in the dot output. However we can do even better by using `set_product_states()` and passing an array of pairs of states. Besides the output routines, some algorithms actually retrieve this vector of pair of states to work on the product.\n", - "\n", - "Regarding the latter point, consider for instance the deterministic nature of these automata. In Spot an automaton is deterministic if it is both existential (no universal branching) and universal (no non-deterministic branching). In our case we will restrict the algorithm to existantial input (by asserting `is_existential()` on both operands), so we can consider that the `prop_universal()` property is an indication of determinism:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(a1.prop_universal())\n", - "print(a2.prop_universal())\n", - "print(prod.prop_universal())\n", - "print(p1.prop_universal())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "yes\n", - "yes\n", - "yes\n", - "maybe\n" - ] - } - ], - "prompt_number": 7 - }, - { - "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", - "\n", - " if left.prop_universal() and right.prop_universal():\n", - " result.prop_universal(True)\n", - " \n", - "at the end of our function. Note that this is **not** the same as\n", - "\n", - " result.prop_universal(left.prop_universal() and right.prop_universal())\n", - "\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_universal(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_universal() and right.prop_universal():\n", - " result.prop_universal(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." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def product3(left, right):\n", - " # the twa_graph.is_existential() method returns a Boolean, not a spot.trival\n", - " if not (left.is_existential() and right.is_existential()):\n", - " raise RuntimeError(\"alternating automata are not supported\")\n", - " bdict = left.get_dict()\n", - " if right.get_dict() != bdict:\n", - " raise RuntimeError(\"automata should share their dictionary\")\n", - " \n", - " result = spot.make_twa_graph(bdict)\n", - " result.copy_ap_of(left)\n", - " result.copy_ap_of(right)\n", - " \n", - " pairs = [] # our array of state pairs\n", - " sdict = {}\n", - " todo = []\n", - " def dst(ls, rs):\n", - " pair = (ls, rs)\n", - " p = sdict.get(pair)\n", - " if p is None:\n", - " p = result.new_state()\n", - " sdict[pair] = p\n", - " todo.append((ls, rs, p))\n", - " pairs.append((ls, rs)) # name each state\n", - " return p\n", - " \n", - " result.set_init_state(dst(left.get_init_state_number(), \n", - " right.get_init_state_number()))\n", - "\n", - " shift = left.num_sets()\n", - " result.set_acceptance(shift + right.num_sets(),\n", - " left.get_acceptance() & (right.get_acceptance() << shift))\n", - " \n", - " while todo:\n", - " lsrc, rsrc, osrc = todo.pop()\n", - " for lt in left.out(lsrc):\n", - " for rt in right.out(rsrc):\n", - " cond = lt.cond & rt.cond\n", - " if cond != buddy.bddfalse:\n", - " acc = lt.acc | (rt.acc << shift)\n", - " result.new_edge(osrc, dst(lt.dst, rt.dst), cond, acc)\n", - "\n", - " # Remember the origin of our states\n", - " result.set_product_states(pairs)\n", - " \n", - " # Loop over all the properties we want to preserve if they hold in both automata\n", - " for p in ('prop_universal', 'prop_complete', 'prop_weak', 'prop_inherently_weak', \n", - " 'prop_terminal', 'prop_stutter_invariant', 'prop_state_acc'):\n", - " if getattr(left, p)() and getattr(right, p)():\n", - " getattr(result, p)(True)\n", - " return result\n", - "\n", - "p3 = product3(a1, a2)\n", - "show_prod(a1, a2, p3)\n", - "print(p3.prop_universal())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "I->1\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a & !b\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "b & c\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b & !c\n", - "\u2777\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - ")\n", - "[gen. B\u00fcchi 3]\n", - "\n", - "\n", - "0\n", - "\n", - "1,0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "0,0\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "0,1\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "2,0\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "2,1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - "" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "yes\n" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For development, it is useful to know that we can force the automaton printer to show the real state numbers (not the pairs) by passing option `1`, and that we can retrieve the associated pairs ourselves." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "display(p3.show('.1'))\n", - "pairs = p3.get_product_states()\n", - "for s in range(p3.num_states()):\n", - " print(\"{}: {}\".format(s, pairs[s]))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!b & c\n", - "\u2776\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!b & !c\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "a & !b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & !b & !c\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "b\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!b & c\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "b & c\n", - "\u24ff\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!b & !c\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "b & !c\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0: (1, 0)\n", - "1: (0, 0)\n", - "2: (0, 1)\n", - "3: (2, 0)\n", - "4: (2, 1)\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Timings\n", - "\n", - "As an indication of how slow it is to implement such an algorithm using the Python bindings of Spot, consider the following comparison:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%timeit product3(a1, a2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "1000 loops, best of 3: 231 \u00b5s per loop\n" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%timeit spot.product(a1, a2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "The slowest run took 5.96 times longer than the fastest. This could mean that an intermediate result is being cached.\n", - "100000 loops, best of 3: 4.6 \u00b5s per loop\n" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Depending on the machine where this notebook has been run, using the C++ version of the product can be 1 to 2 order of magnitude faster. This is due to all the type conversions (converting Python types to C++ types) that occurs everytime a function/method of Spot is called from Python. When calling high-level C++ functions (such as `spot.product()`) from Python, the overhead is negligible because most of the time is spent on the C++ side, actually executing the function. However when calling low-level functions (such as `new_edge()`, `new_state()`, `out()`) most of the time is spent converting the arguments from Python to C++ and the results from C++ to Python.\n", - "\n", - "Despite that speed difference, Python can be useful to prototype an algorithm before implementing it in C++." - ] - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/randaut.ipynb b/tests/python/randaut.ipynb index 0fc76356a..93791a05a 100644 --- a/tests/python/randaut.ipynb +++ b/tests/python/randaut.ipynb @@ -1,4 +1,2269 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "import spot\n", + "spot.setup(size='5,4')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This shows the effect of running `cleanup_acceptance()` on 10 randomly generated automata." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
beforeafter
\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ") | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "[Fin-less 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ") | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ") | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "((Fin(\n", + "\n", + ")|Fin(\n", + "\n", + ")) | Inf(\n", + "\n", + ")) & Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "[gen. Streett 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "[gen. Streett 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))) | Fin(\n", + "\n", + ")\n", + "[gen. Rabin 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))) | Fin(\n", + "\n", + ")\n", + "[gen. Rabin 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "((Fin(\n", + "\n", + ")|Fin(\n", + "\n", + ")) | Inf(\n", + "\n", + ")) & Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ")|Fin(\n", + "\n", + ")) & Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ")|Fin(\n", + "\n", + "))) & Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Inf(\n", + "\n", + ") | (Fin(\n", + "\n", + ")|Fin(\n", + "\n", + "))) & Inf(\n", + "\n", + ")\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!p0 & p1\n", + "\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ")|Fin(\n", + "\n", + ")) | (Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "[Rabin-like 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Fin(\n", + "\n", + ")|Fin(\n", + "\n", + ")) | (Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "[Rabin-like 3]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!p0 & !p1\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "p0 & p1\n", + "\n", + "\n", + "4->1\n", + "\n", + "\n", + "p0 & !p1\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "txt = \"\"\n", + "for a in spot.automata('randaut -A \"random 4\" -H -Q5 -n10 2|'):\n", + " txt += \"\".format(a.show('.a').data, spot.cleanup_acceptance(a).show('.a').data)\n", + "txt += (\"
beforeafter
{0}{1}
\")\n", + "HTML(txt)" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,2278 +2281,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display, HTML\n", - "import spot\n", - "spot.setup(size='5,4')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This shows the effect of running `cleanup_acceptance()` on 10 randomly generated automata." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "txt = \"\"\n", - "for a in spot.automata('randaut -A \"random 4\" -H -Q5 -n10 2|'):\n", - " txt += \"\".format(a.show('.a').data, spot.cleanup_acceptance(a).show('.a').data)\n", - "txt += (\"
beforeafter
{0}{1}
\")\n", - "HTML(txt)" - ], - "language": "python", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "html": [ - "
beforeafter
\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u2776\n", - ") | (Fin(\n", - "\u2777\n", - ") & Fin(\n", - "\u2778\n", - ") & Fin(\n", - "\u24ff\n", - "))\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "t\n", - "[all]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & Fin(\n", - "\u2778\n", - ")) | (Fin(\n", - "\u2777\n", - ") & Inf(\n", - "\u2776\n", - "))\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & Fin(\n", - "\u2777\n", - ")) | Inf(\n", - "\u2776\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Inf(\n", - "\u2777\n", - ") & Fin(\n", - "\u2776\n", - ")) | (Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2778\n", - "))\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u2776\n", - ") | (Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2777\n", - "))\n", - "[Fin-less 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | Fin(\n", - "\u2778\n", - ") | (Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - "))\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ") | Fin(\n", - "\u2778\n", - ") | (Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - "))\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "((Fin(\n", - "\u2776\n", - ")|Fin(\n", - "\u2777\n", - ")) | Inf(\n", - "\u2778\n", - ")) & Inf(\n", - "\u24ff\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "0->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2778\n", - "))\n", - "[gen. Streett 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u2777\n", - ") | Inf(\n", - "\u2776\n", - ")) & (Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2778\n", - "))\n", - "[gen. Streett 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\u2778\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - "))) | Fin(\n", - "\u2778\n", - ")\n", - "[gen. Rabin 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u24ff\n", - ") & (Inf(\n", - "\u2776\n", - ")&Inf(\n", - "\u2777\n", - "))) | Fin(\n", - "\u2778\n", - ")\n", - "[gen. Rabin 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "((Fin(\n", - "\u2777\n", - ")|Fin(\n", - "\u2778\n", - ")) | Inf(\n", - "\u24ff\n", - ")) & Inf(\n", - "\u2776\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2776\n", - "\u2777\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u2776\n", - ")|Fin(\n", - "\u2777\n", - ")) & Inf(\n", - "\u24ff\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "0->3\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "!p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u24ff\n", - ")|Fin(\n", - "\u2777\n", - "))) & Inf(\n", - "\u2778\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Inf(\n", - "\u2776\n", - ") | (Fin(\n", - "\u24ff\n", - ")|Fin(\n", - "\u2777\n", - "))) & Inf(\n", - "\u2778\n", - ")\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "p0 & p1\n", - "\u2778\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!p0 & p1\n", - "\u24ff\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2778\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u2777\n", - "\n", - "\n", - "
\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u2777\n", - ")|Fin(\n", - "\u2778\n", - ")) | (Inf(\n", - "\u24ff\n", - ") & Fin(\n", - "\u2776\n", - "))\n", - "[Rabin-like 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Fin(\n", - "\u2777\n", - ")|Fin(\n", - "\u2778\n", - ")) | (Inf(\n", - "\u24ff\n", - ") & Fin(\n", - "\u2776\n", - "))\n", - "[Rabin-like 3]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "p0 & p1\n", - "\u2777\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "p0 & !p1\n", - "\u2776\n", - "\u2778\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "!p0 & !p1\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!p0 & !p1\n", - "\u24ff\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "p0 & p1\n", - "\n", - "\n", - "4->1\n", - "\n", - "\n", - "p0 & !p1\n", - "\n", - "\n", - "
" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "text": [ - "" - ] - } - ], - "prompt_number": 2 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/randltl.ipynb b/tests/python/randltl.ipynb index 7b69fe532..f777ed6b1 100644 --- a/tests/python/randltl.ipynb +++ b/tests/python/randltl.ipynb @@ -1,4 +1,641 @@ { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Documentation for spot's randltl python binding" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import spot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic usage" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate random formulas from specified atomic propositions:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "0 R b\n", + "F(XG(F!b M Fb) W (b R a))\n" + ] + } + ], + "source": [ + "f = spot.randltl(['a', 'b', 'c'])\n", + "for i in range(3):\n", + " print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate random formulas using 3 atomic propositions:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "0 R p1\n", + "F(XG(F!p1 M Fp1) W (p1 R p0))\n" + ] + } + ], + "source": [ + "f = spot.randltl(3)\n", + "for i in range(3):\n", + " print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, there is no limit to the number of formulas generated.
\n", + "To specify a number of formulas:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "0 R p1\n", + "F(XG(F!p1 M Fp1) W (p1 R p0))\n", + "F(p0 R !p2)\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, 4)\n", + "for formula in f:\n", + " print(formula)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Keyword arguments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## seed" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Seed for the pseudo random number generator (default: 0)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "G(p1 U Gp0)\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, seed=11)\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### output" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Type of formulas to output: 'ltl', 'psl', 'bool' or 'sere' (default: 'ltl')." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{{p0 && p2}[*]}<>-> (Fp2 & Fp0)\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, output='psl', seed=332)\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### allow_dups" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Allow duplicate formulas (default: False)." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "0\n", + "Fp0\n" + ] + } + ], + "source": [ + "f = spot.randltl(1, allow_dups=True)\n", + "print(next(f))\n", + "print(next(f))\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### tree_size" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Tree size of the formulas generated, before mandatory simplifications (default: 15)." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "G(((p0 U !Xp1) M Gp1) U Gp0)\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, tree_size=30, seed=11)\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A range can be specified as a tuple:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X!(Gp1 M p2) R (!p2 M Xp1)\n", + "F(G(F(Gp0 R (1 U Fp2)) M (p2 -> Gp0)) M F((p0 | Fp0) W Gp2))\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, tree_size=(1, 40))\n", + "print(next(f))\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### boolean_priorities, ltl_priorities, sere_priorities, dump_priorities" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "!p2 & (p1 <-> p2)\n", + "p2\n", + "p0 & ((p1 & p2) <-> !(!p0 & p1 & p2))\n", + "1\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, output='bool', boolean_priorities='and=10,or=0')\n", + "for i in range(5):\n", + " print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To see which operators are available along with their default priorities:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Use argument ltl_priorities=STRING to set the following LTL priorities:\n", + "\n", + "ap\t3\n", + "false\t1\n", + "true\t1\n", + "not\t1\n", + "F\t1\n", + "G\t1\n", + "X\t1\n", + "Closure\t1\n", + "equiv\t1\n", + "implies\t1\n", + "xor\t1\n", + "R\t1\n", + "U\t1\n", + "W\t1\n", + "M\t1\n", + "and\t1\n", + "or\t1\n", + "EConcat\t1\n", + "UConcat\t1\n", + "\n", + "Use argument sere_priorities=STRING to set the following SERE priorities:\n", + "\n", + "ap\t3\n", + "false\t1\n", + "true\t1\n", + "not\t1\n", + "F\t1\n", + "G\t1\n", + "X\t1\n", + "Closure\t1\n", + "equiv\t1\n", + "implies\t1\n", + "xor\t1\n", + "R\t1\n", + "U\t1\n", + "W\t1\n", + "M\t1\n", + "and\t1\n", + "or\t1\n", + "EConcat\t1\n", + "UConcat\t1\n", + "eword\t1\n", + "boolform\t1\n", + "star\t1\n", + "star_b\t1\n", + "fstar\t1\n", + "fstar_b\t1\n", + "and\t1\n", + "andNLM\t1\n", + "or\t1\n", + "concat\t1\n", + "fusion\t1\n", + "\n", + "Use argument boolean_priorities=STRING to set the following Boolean formula priorities:\n", + "\n", + "ap\t3\n", + "false\t1\n", + "true\t1\n", + "not\t1\n", + "F\t1\n", + "G\t1\n", + "X\t1\n", + "Closure\t1\n", + "equiv\t1\n", + "implies\t1\n", + "xor\t1\n", + "R\t1\n", + "U\t1\n", + "W\t1\n", + "M\t1\n", + "and\t1\n", + "or\t1\n", + "EConcat\t1\n", + "UConcat\t1\n", + "eword\t1\n", + "boolform\t1\n", + "star\t1\n", + "star_b\t1\n", + "fstar\t1\n", + "fstar_b\t1\n", + "and\t1\n", + "andNLM\t1\n", + "or\t1\n", + "concat\t1\n", + "fusion\t1\n", + "ap\t3\n", + "false\t1\n", + "true\t1\n", + "not\t1\n", + "equiv\t1\n", + "implies\t1\n", + "xor\t1\n", + "and\t1\n", + "or\t1\n", + "\n" + ] + } + ], + "source": [ + "spot.randltl(3, output='psl', dump_priorities=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### simplify" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "0 No rewriting
\n", + "1 basic rewritings and eventual/universal rules
\n", + "2 additional syntactic implication rules
\n", + "3 better implications using containment
\n", + "default: 3" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "G!(!p1 & (Xp2 | F(p0 R Xp2)))\n", + "G(p1 | (X!p2 & G(!p0 U X!p2)))\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, simplify=0, seed=5)\n", + "print(next(f))\n", + "f = spot.randltl(3, simplify=3, seed=5)\n", + "print(next(f))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Filters and maps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "most boolean functions found in the class formula can be used to filter the random formula generator like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "0 R p2\n", + "F(p0 R !p1)\n", + "G(p0 | Fp2) W (FGp2 R !p2)\n", + "(p2 R G!p1) | G(p2 U !p0)\n", + "(p2 W p0) U p2\n", + "F!G(!Gp1 W p1)\n", + "G!p1 & (!((p2 & Fp1) M p1) U p1)\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, 20).is_syntactic_stutter_invariant()\n", + "for formula in f:\n", + " print(formula)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "likewise, functions from formula to formula can be applied to map the iterator:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "!(F!p1 M 1)\n", + "(Gp0 | Fp1) M 1\n", + "F!(!p1 <-> FGp1)\n", + "Gp1 U (p1 U GFp1)\n", + "(!p1 U p1) U ((p0 & (p0 U (!p0 & (!p0 -> Fp1))) & ((!p1 U !p0) | (p1 U !p0))) | (!p0 & (!p0 U (p0 & (!p0 -> Fp1))) & ((!p1 U p0) | (p1 U p0))) | (p1 & (p1 U (!p1 & (!p0 -> Fp1))) & ((!p0 U !p1) | (p0 U !p1))) | (!p1 & (!p1 U (p1 & (!p0 -> Fp1))) & ((!p0 U p1) | (p0 U p1))) | ((!p0 -> Fp1) & (Gp0 | G!p0) & (Gp1 | G!p1)))\n" + ] + } + ], + "source": [ + "f = spot.randltl(2, 6).remove_x()\n", + "for formula in f:\n", + " print(formula)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the boolean filters and mapping functions return an iterator of the same type, these operations can be chained like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "Ga\n", + "F(a R !b)\n", + "G(a | Fb) | (FGb R !b)\n", + "G!b | G(a U !c)\n", + "b U a\n", + "0\n", + "0\n" + ] + } + ], + "source": [ + "f = spot.randltl(3, 20).is_syntactic_stutter_invariant().relabel(spot.Abc).simplify()\n", + "for formula in f:\n", + " print(formula)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "!(1 U !p1)\n", + "1 U ((p0 U ((p0 & p1) | !(1 U !p0))) | !(1 U !((1 U !p1) & (1 U p1))))\n", + "1 U (!p2 U ((p0 & !p2) | !(1 U p2)))\n", + "(!p1 U ((!p1 & (1 U !(1 U !p1))) | !(1 U p1))) | !(1 U !(p0 | (1 U p1)))\n", + "X(p2 & X(p2 U (!p0 | !(1 U !p2))))\n", + "(1 U p2) | (X(!p2 | !(1 U !p2)) U ((1 U p2) U (!p1 & (1 U p2))))\n", + "XX!(1 U !((X!p1 U (!p2 U (!p0 & !p2))) | X!(1 U !p0)))\n", + "XX(1 U (p1 U ((p0 & p1) | !(1 U !p1))))\n", + "p2 & Xp0\n" + ] + } + ], + "source": [ + "for formula in spot.randltl(3, 10).simplify().unabbreviate(\"WMGFR\"): print(formula)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,662 +653,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3+" - }, - "name": "", - "signature": "sha256:c1de5aacd024bbec64b75f61a13e53562185c906051312d9ce5067236b7899d4" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "heading", - "level": 1, - "metadata": {}, - "source": [ - "Documentation for spot's randltl python binding" - ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "import spot" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "Basic usage" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate random formulas from specified atomic propositions:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(['a', 'b', 'c'])\n", - "for i in range(3):\n", - " print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "0 R b\n", - "F(XG(F!b M Fb) W (b R a))\n" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generate random formulas using 3 atomic propositions:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3)\n", - "for i in range(3):\n", - " print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "0 R p1\n", - "F(XG(F!p1 M Fp1) W (p1 R p0))\n" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, there is no limit to the number of formulas generated.
\n", - "To specify a number of formulas:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, 4)\n", - "for formula in f:\n", - " print(formula)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "0 R p1\n", - "F(XG(F!p1 M Fp1) W (p1 R p0))\n", - "F(p0 R !p2)\n" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "Keyword arguments" - ] - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "seed" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Seed for the pseudo random number generator (default: 0)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, seed=11)\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "G(p1 U Gp0)\n" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "output" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Type of formulas to output: 'ltl', 'psl', 'bool' or 'sere' (default: 'ltl')." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, output='psl', seed=332)\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "{{p0 && p2}[*]}<>-> (Fp2 & Fp0)\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "allow_dups" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Allow duplicate formulas (default: False)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(1, allow_dups=True)\n", - "print(next(f))\n", - "print(next(f))\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "0\n", - "Fp0\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "tree_size" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tree size of the formulas generated, before mandatory simplifications (default: 15)." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, tree_size=30, seed=11)\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "G(((p0 U !Xp1) M Gp1) U Gp0)\n" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A range can be specified as a tuple:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, tree_size=(1, 40))\n", - "print(next(f))\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "X!(Gp1 M p2) R (!p2 M Xp1)\n", - "F(G(F(Gp0 R (1 U Fp2)) M (p2 -> Gp0)) M F((p0 | Fp0) W Gp2))\n" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "boolean_priorities, ltl_priorities, sere_priorities, dump_priorities" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, output='bool', boolean_priorities='and=10,or=0')\n", - "for i in range(5):\n", - " print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "!p2 & (p1 <-> p2)\n", - "p2\n", - "p0 & ((p1 & p2) <-> !(!p0 & p1 & p2))\n", - "1\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To see which operators are available along with their default priorities:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.randltl(3, output='psl', dump_priorities=True)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Use argument ltl_priorities=STRING to set the following LTL priorities:\n", - "\n", - "ap\t3\n", - "false\t1\n", - "true\t1\n", - "not\t1\n", - "F\t1\n", - "G\t1\n", - "X\t1\n", - "Closure\t1\n", - "equiv\t1\n", - "implies\t1\n", - "xor\t1\n", - "R\t1\n", - "U\t1\n", - "W\t1\n", - "M\t1\n", - "and\t1\n", - "or\t1\n", - "EConcat\t1\n", - "UConcat\t1\n", - "\n", - "Use argument sere_priorities=STRING to set the following SERE priorities:\n", - "\n", - "ap\t3\n", - "false\t1\n", - "true\t1\n", - "not\t1\n", - "F\t1\n", - "G\t1\n", - "X\t1\n", - "Closure\t1\n", - "equiv\t1\n", - "implies\t1\n", - "xor\t1\n", - "R\t1\n", - "U\t1\n", - "W\t1\n", - "M\t1\n", - "and\t1\n", - "or\t1\n", - "EConcat\t1\n", - "UConcat\t1\n", - "eword\t1\n", - "boolform\t1\n", - "star\t1\n", - "star_b\t1\n", - "fstar\t1\n", - "fstar_b\t1\n", - "and\t1\n", - "andNLM\t1\n", - "or\t1\n", - "concat\t1\n", - "fusion\t1\n", - "\n", - "Use argument boolean_priorities=STRING to set the following Boolean formula priorities:\n", - "\n", - "ap\t3\n", - "false\t1\n", - "true\t1\n", - "not\t1\n", - "F\t1\n", - "G\t1\n", - "X\t1\n", - "Closure\t1\n", - "equiv\t1\n", - "implies\t1\n", - "xor\t1\n", - "R\t1\n", - "U\t1\n", - "W\t1\n", - "M\t1\n", - "and\t1\n", - "or\t1\n", - "EConcat\t1\n", - "UConcat\t1\n", - "eword\t1\n", - "boolform\t1\n", - "star\t1\n", - "star_b\t1\n", - "fstar\t1\n", - "fstar_b\t1\n", - "and\t1\n", - "andNLM\t1\n", - "or\t1\n", - "concat\t1\n", - "fusion\t1\n", - "ap\t3\n", - "false\t1\n", - "true\t1\n", - "not\t1\n", - "equiv\t1\n", - "implies\t1\n", - "xor\t1\n", - "and\t1\n", - "or\t1\n", - "\n" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "simplify" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "0 No rewriting
\n", - "1 basic rewritings and eventual/universal rules
\n", - "2 additional syntactic implication rules
\n", - "3 better implications using containment
\n", - "default: 3" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, simplify=0, seed=5)\n", - "print(next(f))\n", - "f = spot.randltl(3, simplify=3, seed=5)\n", - "print(next(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "G!(!p1 & (Xp2 | F(p0 R Xp2)))\n", - "G(p1 | (X!p2 & G(!p0 U X!p2)))\n" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "Filters and maps" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "most boolean functions found in the class formula can be used to filter the random formula generator like this:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, 20).is_syntactic_stutter_invariant()\n", - "for formula in f:\n", - " print(formula)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "0 R p2\n", - "F(p0 R !p1)\n", - "G(p0 | Fp2) W (FGp2 R !p2)\n", - "(p2 R G!p1) | G(p2 U !p0)\n", - "(p2 W p0) U p2\n", - "F!G(!Gp1 W p1)\n", - "G!p1 & (!((p2 & Fp1) M p1) U p1)\n" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "likewise, functions from formula to formula can be applied to map the iterator:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(2, 6).remove_x()\n", - "for formula in f:\n", - " print(formula)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "!(F!p1 M 1)\n", - "(Gp0 | Fp1) M 1\n", - "F!(!p1 <-> FGp1)\n", - "Gp1 U (p1 U GFp1)\n", - "(!p1 U p1) U ((p0 & (p0 U (!p0 & (!p0 -> Fp1))) & ((!p1 U !p0) | (p1 U !p0))) | (!p0 & (!p0 U (p0 & (!p0 -> Fp1))) & ((!p1 U p0) | (p1 U p0))) | (p1 & (p1 U (!p1 & (!p0 -> Fp1))) & ((!p0 U !p1) | (p0 U !p1))) | (!p1 & (!p1 U (p1 & (!p0 -> Fp1))) & ((!p0 U p1) | (p0 U p1))) | ((!p0 -> Fp1) & (Gp0 | G!p0) & (Gp1 | G!p1)))\n" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since the boolean filters and mapping functions return an iterator of the same type, these operations can be chained like this:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.randltl(3, 20).is_syntactic_stutter_invariant().relabel(spot.Abc).simplify()\n", - "for formula in f:\n", - " print(formula)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "Ga\n", - "F(a R !b)\n", - "G(a | Fb) | (FGb R !b)\n", - "G!b | G(a U !c)\n", - "b U a\n", - "0\n", - "0\n" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "for formula in spot.randltl(3, 10).simplify().unabbreviate(\"WMGFR\"): print(formula)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "!(1 U !p1)\n", - "1 U ((p0 U ((p0 & p1) | !(1 U !p0))) | !(1 U !((1 U !p1) & (1 U p1))))\n", - "1 U (!p2 U ((p0 & !p2) | !(1 U p2)))\n", - "(!p1 U ((!p1 & (1 U !(1 U !p1))) | !(1 U p1))) | !(1 U !(p0 | (1 U p1)))\n", - "X(p2 & X(p2 U (!p0 | !(1 U !p2))))\n", - "(1 U p2) | (X(!p2 | !(1 U !p2)) U ((1 U p2) U (!p1 & (1 U p2))))\n", - "XX!(1 U !((X!p1 U (!p2 U (!p0 & !p2))) | X!(1 U !p0)))\n", - "XX(1 U (p1 U ((p0 & p1) | !(1 U !p1))))\n", - "p2 & Xp0\n" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 16 - } - ], - "metadata": {} } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/python/stutter-inv.ipynb b/tests/python/stutter-inv.ipynb index 756baf59f..aa5f0ae9e 100644 --- a/tests/python/stutter-inv.ipynb +++ b/tests/python/stutter-inv.ipynb @@ -1,4 +1,2815 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup(show_default='.ban')\n", + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stutter-invariant languages\n", + "\n", + "A language $L$ is said to be _stutter-invariant_ iff $\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_{i+1}\\ldots\\in L \\iff \\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_i\\ell_{i+1}\\ldots\\in L$, i.e., if duplicating a letter in a word or removing a duplicated letter does not change the membership of that word to $L$. These languages are also called _stutter-insensitive_. We use the adjective _sutter-sensitive_ to describe a language that is not stutter-invariant. Of course we can extend this vocabulary to LTL formulas or automata that represent stutter-invariant languages.\n", + "\n", + "Stutter-invariant languages play an important role in model checking. When verifying a stutter-invariant specification against a system, we know that we have some freedom in how we discretize the time in the model: as long as we do not hide changes of model variables that are observed by the specification, we can merge multiple steps of the model. This, combined by careful analysis of actions of the model that are independent, is the basis for a set of techniques known as _partial-order reductions_ (POR) that postpone the visit of some successors in the model, because we know we can always visit them later." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stutter-invariant formulas\n", + "\n", + "When the specification is expressed as an LTL formula, a well known way to ensure it is _stutter-invariant_ is to forbid the use of the `X` operator. Testing whether a formula is `X`-free can be done in constant time using the `is_syntactic_stutter_invariant()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "f = spot.formula('a U b')\n", + "print(f.is_syntactic_stutter_invariant())" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "f = spot.formula('a U Xb')\n", + "print(f.is_syntactic_stutter_invariant())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However some formula are syntactic-invariant despite their use of `X`. Spot implements some [automaton-based check](https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf) to detect stutter-invariance reliably and efficiently. This can be tested with the `is_stutter_invariant()` function." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "True\n" + ] + } + ], + "source": [ + "g = spot.formula('F(a & X(!a & Gb))')\n", + "print(g.is_syntactic_stutter_invariant())\n", + "print(spot.is_stutter_invariant(g))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Of course this `is_stutter_invariant()` function first checks whether the formula is `X`-free before wasting time building automata, so if you want to detect stutter-invariant formulas in your model checker, this is the only function to use. Also, if you hapen to already have an automaton `aut_g` for `g`, you should pass it as a second argument to avoid it being recomputed: `spot.is_stutter_invariant(g, aut_g)`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is also known that any stutter-invariant LTL formula can be converted to an `X`-free LTL formula. Several proofs of that exist. Spot implements the rewriting of [K. Etessami](http://homepages.inf.ed.ac.uk/kousha/note_on_stut_tl_lpi.ps) under the name `remove_x()`. Note that the output of this function is only equivalent to its input if the latter is stutter-invariant." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\mathsf{F} (a \\land ((a \\land (a \\mathbin{\\mathsf{U}} (\\lnot a \\land \\mathsf{G} b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} \\lnot a) \\lor (b \\mathbin{\\mathsf{U}} \\lnot a))) \\lor (\\lnot a \\land (\\lnot a \\mathbin{\\mathsf{U}} (a \\land \\lnot a \\land \\mathsf{G} b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} a) \\lor (b \\mathbin{\\mathsf{U}} a))) \\lor (b \\land (b \\mathbin{\\mathsf{U}} (\\lnot a \\land \\lnot b \\land \\mathsf{G} b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} \\lnot b) \\lor (a \\mathbin{\\mathsf{U}} \\lnot b))) \\lor (\\lnot b \\land (\\lnot b \\mathbin{\\mathsf{U}} (\\lnot a \\land b \\land \\mathsf{G} b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} b) \\lor (a \\mathbin{\\mathsf{U}} b))) \\lor (\\lnot a \\land \\mathsf{G} b \\land (\\mathsf{G} \\lnot a \\lor \\mathsf{G} a) \\land (\\mathsf{G} b \\lor \\mathsf{G} \\lnot b))))$" + ], + "text/plain": [ + "F(a & ((a & (a U (!a & Gb)) & ((!b U !a) | (b U !a))) | (!a & (!a U (a & !a & Gb)) & ((!b U a) | (b U a))) | (b & (b U (!a & !b & Gb)) & ((!a U !b) | (a U !b))) | (!b & (!b U (!a & b & Gb)) & ((!a U b) | (a U b))) | (!a & Gb & (G!a | Ga) & (Gb | G!b))))" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.remove_x(g)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stutter-invariant automata" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly to formulas, automata use a few bits to store some known properties about themselves, like whether they represent a stutter-invariant language. This property can be checked with the `prop_stutter_invariant()` method, but that returns a `trival` instance (i.e., yes, no, or maybe). Some algorithms will update that property whenever that is cheap or expliclitely asked for. For instance `spot.translate()` only sets the property if the translated formula is `X`-free." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "maybe\n" + ] + } + ], + "source": [ + "aut = spot.translate(g)\n", + "print(aut.prop_stutter_invariant())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As suggested above, we can call `is_stutter_invariant()` by passing a formula and its automaton, to save on one translation. A second translation is still needed to complement the automaton." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "print(spot.is_stutter_invariant(g, aut))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that `prop_stutter_invariant()` was updated as a side-effect so that any futher call to `is_stutter_invariant()` with this automaton will be instantaneous." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "yes\n" + ] + } + ], + "source": [ + "print(aut.prop_stutter_invariant())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have to be aware of this property being set in your back because if while playing with `is_stutter_invariant()` you the incorrect formula for an automaton by mistake, the automaton will have its property set incorrectly, and running `is_stutter_inariant()` with the correct formula will simply return the cached property.\n", + "\n", + "In doubt, you can always reset the property as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "maybe\n" + ] + } + ], + "source": [ + "aut.prop_stutter_invariant(spot.trival_maybe())\n", + "print(aut.prop_stutter_invariant())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In case you have an automaton for which you do not have formula, you can also use `is_stutter_invariant()` by passing this automaton as the first argument. In that case a negated automaton will be constructed by determinization. If you do happen to have a negated automaton handy, you can pass it as a second argument to avoid that." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce55870> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "a1 = spot.automaton('''HOA: v1 \n", + "AP: 1 \"a\" \n", + "States: 2 \n", + "Start: 0 \n", + "Acceptance: 0 t\n", + "--BODY-- \n", + "State: 0 [0] 1 \n", + "State: 1 [t] 0 \n", + "--END--''')\n", + "display(a1)\n", + "print(spot.is_stutter_invariant(a1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Explaining why a formula is not sutter-invariant" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As explained in our [Spin'15 paper](https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf) the sutter-invariant checks are implemented using simple operators suchs as `spot.closure(aut)`, that augment the language of L by adding words that can be obtained by removing duplicated letters, and `spot.sl(aut)` or `spot.sl2(aut)` that both augment the language that L by adding words that can be obtained by duplicating letters. The default `is_stutter_invariant()` function is implemented as `spot.product(spot.closure(aut), spot.closure(neg_aut)).is_empty()`, but that is just one possible implementation selected because it was more efficient.\n", + "\n", + "Using these bricks, we can modify the original algorithm so it uses a counterexample to explain why a formula is stutter-sensitive." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def explain_stut(f):\n", + " f = spot.formula(f)\n", + " pos = spot.translate(f)\n", + " neg = spot.translate(spot.formula_Not(f))\n", + " word = spot.product(spot.closure(pos), spot.closure(neg)).accepting_word()\n", + " if word is None:\n", + " print(f, \"is stutter invariant\")\n", + " return\n", + " word.simplify()\n", + " waut = word.as_automaton()\n", + " if waut.intersects(pos):\n", + " acc, rej, aut = \"accepted\", \"rejected\", neg\n", + " else:\n", + " acc, rej, aut = \"rejected\", \"accepted\", pos\n", + " word2 = spot.sl2(waut).intersecting_word(aut)\n", + " word2.simplify()\n", + " print(\"\"\"{} is {} by {}\n", + " but if we stutter some of its letters, we get\n", + "{} which is {} by {}\"\"\".format(word, acc, f, word2, rej, f))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cycle{!a & !b; a & b} is rejected by GF(a & Xb)\n", + " but if we stutter some of its letters, we get\n", + "cycle{!a & !b; a & b; a & b} which is accepted by GF(a & Xb)\n" + ] + } + ], + "source": [ + "explain_stut('GF(a & Xb)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Detecting stutter-invariant states\n", + "\n", + "Even if the language of an automaton is not sutter invariant, some of its states may recognize a stutter-invariant language. (We assume the language of a state is the language the automaton would have when starting from this state.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First example\n", + "\n", + "For instance let us build a disjunction of a stutter-invariant formula and a stutter-sensitive one:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n", + "False\n" + ] + } + ], + "source": [ + "f1 = spot.formula('F(a & X!a & XF(b & X!b & Ga))')\n", + "f2 = spot.formula('F(a & Xa & XXa & G!b)')\n", + "f = spot.formula_Or([f1, f2])\n", + "\n", + "print(spot.is_stutter_invariant(f1))\n", + "print(spot.is_stutter_invariant(f2))\n", + "print(spot.is_stutter_invariant(f))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce2e900> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pos = spot.translate(f)\n", + "display(pos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While the automaton as a whole is stutter-sensitive, we can see that eventually we will enter a sub-automaton that is stutter-invariant.\n", + "\n", + "The `stutter_invariant_states()` function returns a Boolean vector indiced by the state number. A state is marked as `True` if either its language is stutter-invariant, or if it can only be reached via a stutter-invariant state (see the second example later). As always, the second argument, `f`, can be omitted (pass `None`) if the formula is unknown, or it can be replaced by a negated automaton if it is known. " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(False, True, False, True, True, True, True, True)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.stutter_invariant_states(pos, f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For convenience, the `highligh_...()` version colors the stutter-invariant states of the automaton for display.\n", + "(That 5 is the color number for red in Spot's hard-coded palette.)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "4->7\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "7->7\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce2e900> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "spot.highlight_stutter_invariant_states(pos, f, 5)\n", + "display(pos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Such a procedure gives us map of where POR can be enabled when model checking using such an automaton." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Second example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This second example illustrates the fact that a state can be marked if it it not sutter-invariant but appear below a stutter-invariant state. We build our example automaton as the disjuction of the following two stutter-sensitive formulas, whose union is equivalent to the sutter-invariant formula `GF!a`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "g1 = spot.formula('GF(a & Xa) & GF!a')\n", + "g2 = spot.formula('!GF(a & Xa) & GF!a')\n", + "g = spot.formula_Or([g1, g2])" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "False\n", + "True\n" + ] + } + ], + "source": [ + "print(spot.is_stutter_invariant(g1))\n", + "print(spot.is_stutter_invariant(g2))\n", + "print(spot.is_stutter_invariant(g))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here are the automata for `g1` and `g2`, note that none of the states are stutter-invariant." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "G(F(a & Xa) & F!a)\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce2e8d0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "FG(!a | X!a)\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce61d50> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut1 = spot.translate(g1)\n", + "aut1.set_name(str(g1))\n", + "spot.highlight_stutter_invariant_states(aut1, g1, 5)\n", + "display(aut1)\n", + "\n", + "aut2 = spot.translate(g2)\n", + "aut2.set_name(str(g2))\n", + "spot.highlight_stutter_invariant_states(aut2, g2, 5)\n", + "display(aut2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we build the sum of these two automata. The stutter-invariance check detects that the initial state is stutter-invariant (i.e., the entire language is stutter-invariant) so all states below it are marked despite the fact that the language recognized from these individual states would not be stutter-invariant." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | Inf(\n", + "\n", + ")\n", + "[Fin-less 3]\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "I->5\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "5->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "5->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "5->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce2ea50> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HOA: v1\n", + "States: 6\n", + "Start: 5\n", + "AP: 1 \"a\"\n", + "Acceptance: 3 (Inf(0)&Inf(1)) | Inf(2)\n", + "properties: trans-labels explicit-labels trans-acc stutter-invariant\n", + "--BODY--\n", + "State: 0\n", + "[!0] 0 {1}\n", + "[0] 0\n", + "[0] 1 {0}\n", + "State: 1\n", + "[0] 0\n", + "[0] 1 {0}\n", + "State: 2\n", + "[t] 2\n", + "[!0] 3\n", + "[0] 4\n", + "State: 3\n", + "[!0] 3 {2}\n", + "[0] 4 {2}\n", + "State: 4\n", + "[!0] 3 {2}\n", + "State: 5\n", + "[!0] 3\n", + "[0] 1\n", + "[0] 4\n", + "[t] 0\n", + "[t] 2\n", + "--END--\n" + ] + } + ], + "source": [ + "aut = spot.sum(aut1, aut2)\n", + "# At this point it is unknown if AUT is stutter-invariant\n", + "assert(aut.prop_stutter_invariant().is_maybe())\n", + "spot.highlight_stutter_invariant_states(aut, g, 5)\n", + "display(aut)\n", + "# The stutter_invariant property is set on AUT as a side effect\n", + "# of calling sutter_invariant_states() or any variant of it.\n", + "assert(aut.prop_stutter_invariant().is_true())\n", + "\n", + "print(aut.to_str())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Third example\n", + "\n", + "These procedures work regardless of the acceptance condition. Here is an example with co-Büchi acceptance.\n", + "\n", + "In this case we do not even have a formula to pass as second argument, so the check will perform a complementation by determinization." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Fin(\n", + "\n", + ")\n", + "[co-Büchi]\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce2e960> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "aut = spot.automaton('randaut --seed=30 -Q4 -A\"Fin(0)\" a |')\n", + "spot.highlight_stutter_invariant_states(aut, None, 5)\n", + "display(aut)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the negated automaton is already known, it can be passed as second argument (instead of the positive formula) to avoid unnecessary work." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sutter-invariance at the letter level\n", + "\n", + "Instead of marking each state as stuttering or not, we can list the letters that we can stutter in each state.\n", + "More precisely, a state $q$ is _stutter-invariant for letter $a$_ if the membership to $L(q)$ of any word starting with $a$ is preserved by the operations that duplicate letters or remove duplicates. \n", + "\n", + "$(\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_{i+1}\\ldots\\in L(q) \\land \\ell_0=a) \\iff (\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_i\\ell_{i+1}\\ldots\\in L(q)\\land \\ell_0=a)$\n", + "\n", + "Under this definition, we can also say that $q$ is _stutter-invariant_ iff it is _stutter-invariant for any letter_.\n", + "\n", + "For instance consider the following automaton, for which all words that start with $b$ are stutter invariant.\n", + "The initial state may not be declared as stutter-invariant because of words that start with $\\lnot b$." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "I->3\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "3->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79ce55e10> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f = spot.formula('(!b&Xa) | Gb')\n", + "pos = spot.translate(f)\n", + "spot.highlight_stutter_invariant_states(pos, f, 5)\n", + "display(pos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `stutter_invariant_letters()` functions returns a vector of BDDs indexed by state numbers. The BDD at index $q$ specifies all letters $\\ell$ for which state $q$ would be stuttering. Note that if $q$ is stutter-invariant or reachable from a stutter-invariant state, the associated BDD will be `bddtrue` (printed as `1` below).\n", + "\n", + "This interface is a bit inconveniant to use interactively, due to the fact that we need a `spot.bdd_dict` object to print a BDD." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sil_vec[0] = 1\n", + "sil_vec[1] = 1\n", + "sil_vec[2] = 1\n", + "sil_vec[3] = b\n" + ] + } + ], + "source": [ + "sil_vec = spot.stutter_invariant_letters(pos, f)\n", + "for q in range(pos.num_states()):\n", + " print(\"sil_vec[{}] =\".format(q), spot.bdd_format_formula(pos.get_dict(), sil_vec[q]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The set of stutter-invariant states is not always forward closed\n", + "\n", + "Consider the following automaton, which is a variant of our second example above. \n", + "\n", + "The language accepted from state (2) is `!GF(a & Xa) & GF!a` (this can be simplified to `FG(!a | X!a)`), while the language accepted from state (0) is `GF(a & Xa) & GF!a`. Therefore. the language accepted from state (5) is `a & X(GF!a)`. Since this is equivalent to `a & GF(!a)` state (5) recognizes stutter-invariant language, but as we can see, it is not the case that all states below (5) are also marked. In fact, states (0) can also be reached via states (7) and (6), recognizing respectively `(a & X(a & GF!a)) | (!a & X(!a & GF(a & Xa) & GF!a))` and `!a & GF(a & Xa) & GF!a))`, i.e., two stutter-sentive languages." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "I->7\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "7->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "7->6\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "5->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "6->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79cdf1ba0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ex1 = spot.automaton(\"\"\"HOA: v1 \n", + "States: 8 Start: 7 AP: 1 \"a\" Acceptance: 2 (Inf(0)&Inf(1))\n", + "--BODY--\n", + "State: 0 [!0] 0 {1} [0] 0 [0] 1 {0}\n", + "State: 1 [0] 0 [0] 1 {0}\n", + "State: 2 [t] 2 [!0] 3 [0] 4\n", + "State: 3 [!0] 3 {0 1} [0] 4 {0 1}\n", + "State: 4 [!0] 3 {0 1}\n", + "State: 5 [0] 0 [0] 2\n", + "State: 6 [!0] 0\n", + "State: 7 [!0] 6 [0] 5\n", + "--END--\"\"\")\n", + "spot.highlight_stutter_invariant_states(ex1,None, 5)\n", + "display(ex1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This situation can be tested with `spot.is_stutter_invariant_forward_closed()`. The function returns `-1` if the successor of any stutter-invariant state is it is also a stutter-invariant state, otherwise it return the number of one stutter-sensitive state that has a stutter-invariant state as predecessor." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sistates = spot.stutter_invariant_states(ex1)\n", + "spot.is_stutter_invariant_forward_closed(ex1, sistates)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In cases where we prefer to have a forward-closed set of stutter-invariant states, it is always possible to duplicate\n", + "the problematic states. The `make_stutter_invariant_foward_closed_inplace()` modifies the automaton in place, and also returns an updated copie of the vector of stutter-invariant states." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")\n", + "[gen. Büchi 2]\n", + "\n", + "\n", + "7\n", + "\n", + "7\n", + "\n", + "\n", + "I->7\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "7->5\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "6\n", + "\n", + "6\n", + "\n", + "\n", + "7->6\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "2->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "\n", + "5->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8\n", + "\n", + "8\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "8->8\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "9\n", + "\n", + "9\n", + "\n", + "\n", + "8->9\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "6->0\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "9->8\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "9->9\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fc79cdf1ba0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(False, False, True, True, True, True, False, False, True, True)\n" + ] + } + ], + "source": [ + "sistates2 = spot.make_stutter_invariant_forward_closed_inplace(ex1, sistates)\n", + "spot.highlight_stutter_invariant_states(ex1, None, 5)\n", + "display(ex1)\n", + "print(sistates2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, state 0 is no longuer a problem." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-1" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.is_stutter_invariant_forward_closed(ex1, sistates2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's see how infrequently the set of stutter-invarant states is not closed." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot.gen as gen\n", + "\n", + "try:\n", + " import pandas\n", + "except ImportError:\n", + " import sys; sys.exit(77) # Our test suite will skip the rest if Pandas is missing" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
formulastatesSIstatesfwd_closed
0Fp0 -> (!p0 U (!p0 & p1 & X(!p0 U p2)))32True
1Fp0 -> (!p1 U (p0 | (!p1 & p2 & X(!p1 U p3))))43True
2G!p0 | (!p0 U ((p0 & Fp1) -> (!p1 U (!p1 & p2 ...42True
3G((p0 & Fp1) -> (!p2 U (p1 | (!p2 & p3 & X(!p2...41True
4G(p0 -> (Fp1 -> (!p1 U (p2 | (!p1 & p3 & X(!p1...30True
5F(p0 & XFp1) -> (!p0 U p2)32True
6Fp0 -> (!(!p0 & p1 & X(!p0 U (!p0 & p2))) U (p...43True
7G!p0 | (!p0 U (p0 & (F(p1 & XFp2) -> (!p1 U p3...42True
8G((p0 & Fp1) -> (!(!p1 & p2 & X(!p1 U (!p1 & p...41True
9G(p0 -> ((!(!p1 & p2 & X(!p1 U (!p1 & p3))) U ...30True
10G((p0 & XFp1) -> XF(p1 & Fp2))61True
11Fp0 -> (((p1 & X(!p0 U p2)) -> X(!p0 U (p2 & F...62True
12G(p0 -> G((p1 & XFp2) -> X(!p2 U (p2 & Fp3))))50True
13G((p0 & Fp1) -> (((p2 & X(!p1 U p3)) -> X(!p1 ...102True
14G(p0 -> (((p1 & X(!p2 U p3)) -> X(!p2 U (p3 & ...100True
15G(p0 -> F(p1 & XFp2))40True
16Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & X(!p0 U p3))...41True
17G(p0 -> G(p1 -> (p2 & XFp3)))33True
18G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & X(!...40True
19G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & X(!p2 U p4)...62True
20G(p0 -> F(p1 & !p2 & X(!p2 U p3)))40True
21Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & !p3 & X((!p0...41True
22G(p0 -> G(p1 -> (p2 & !p3 & X(!p3 U p4))))33True
23G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & !p4...40True
24G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & !p4 & X((!p...62True
25p0 U (p1 & X(p2 U p3))32True
26p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)...72True
27F(p0 & XGp1)22True
28F(p0 & X(p1 & XFp2))42True
29F(p0 & X(p1 U p2))31True
...............
33G((p0 & p1 & !p2 & Xp2) -> X(p3 | X(!p1 | p3)))30True
34G((p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2...55True
35G(p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2 ...11True
36G((!p0 & p1) -> Xp2)20True
37G(p0 -> X(p0 | p1))22True
38G((!(p1 <-> Xp1) | !(p0 <-> Xp0) | !(p2 <-> Xp...3434True
39G((p0 & !p1 & Xp1 & Xp0) -> (p2 -> Xp3))22True
40G(p0 -> X(!p0 U p1))20True
41G((!p0 & Xp0) -> X((p0 U p1) | Gp0))33True
42G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1))))44True
43G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1 ...66True
44G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ...66True
45G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ...88True
46G((!p0 & Xp0) -> X(!(!p0 & Xp0) U (!p1 & Xp1)))66True
47G(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 ...120True
48G((Xp0 -> p0) -> (p1 <-> Xp1))44True
49G((Xp0 -> p0) -> ((p1 -> Xp1) & (!p1 -> X!p1)))44True
50p0 & XG!p021True
51XG(p0 -> (G!p1 | (!Xp1 U p2)))41True
52XG((p0 & !p1) -> (G!p1 | (!p1 U p2)))32True
53XG((p0 & p1) -> (Gp1 | (p1 U p2)))32True
54Xp0 & G((!p0 & Xp0) -> XXp0)50True
55(Xp0 U Xp1) | !X(p0 U p1)11True
56(Xp0 U p1) | !X(p0 U (p0 & p1))11True
57((Xp0 U p1) | !X(p0 U (p0 & p1))) & G(p0 -> Fp1)22True
58((Xp0 U Xp1) | !X(p0 U p1)) & G(p0 -> Fp1)22True
59!G(p0 -> X(p1 R p2))31True
60(p0 & Xp1) R X(((p2 U p3) R p0) U (p2 R p0))53True
61G(p0 | XGp1) & G(p2 | XG!p1)32True
62G(p0 | (Xp1 & X!p1))11True
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " formula states SIstates \\\n", + "0 Fp0 -> (!p0 U (!p0 & p1 & X(!p0 U p2))) 3 2 \n", + "1 Fp0 -> (!p1 U (p0 | (!p1 & p2 & X(!p1 U p3)))) 4 3 \n", + "2 G!p0 | (!p0 U ((p0 & Fp1) -> (!p1 U (!p1 & p2 ... 4 2 \n", + "3 G((p0 & Fp1) -> (!p2 U (p1 | (!p2 & p3 & X(!p2... 4 1 \n", + "4 G(p0 -> (Fp1 -> (!p1 U (p2 | (!p1 & p3 & X(!p1... 3 0 \n", + "5 F(p0 & XFp1) -> (!p0 U p2) 3 2 \n", + "6 Fp0 -> (!(!p0 & p1 & X(!p0 U (!p0 & p2))) U (p... 4 3 \n", + "7 G!p0 | (!p0 U (p0 & (F(p1 & XFp2) -> (!p1 U p3... 4 2 \n", + "8 G((p0 & Fp1) -> (!(!p1 & p2 & X(!p1 U (!p1 & p... 4 1 \n", + "9 G(p0 -> ((!(!p1 & p2 & X(!p1 U (!p1 & p3))) U ... 3 0 \n", + "10 G((p0 & XFp1) -> XF(p1 & Fp2)) 6 1 \n", + "11 Fp0 -> (((p1 & X(!p0 U p2)) -> X(!p0 U (p2 & F... 6 2 \n", + "12 G(p0 -> G((p1 & XFp2) -> X(!p2 U (p2 & Fp3)))) 5 0 \n", + "13 G((p0 & Fp1) -> (((p2 & X(!p1 U p3)) -> X(!p1 ... 10 2 \n", + "14 G(p0 -> (((p1 & X(!p2 U p3)) -> X(!p2 U (p3 & ... 10 0 \n", + "15 G(p0 -> F(p1 & XFp2)) 4 0 \n", + "16 Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & X(!p0 U p3))... 4 1 \n", + "17 G(p0 -> G(p1 -> (p2 & XFp3))) 3 3 \n", + "18 G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & X(!... 4 0 \n", + "19 G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & X(!p2 U p4)... 6 2 \n", + "20 G(p0 -> F(p1 & !p2 & X(!p2 U p3))) 4 0 \n", + "21 Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & !p3 & X((!p0... 4 1 \n", + "22 G(p0 -> G(p1 -> (p2 & !p3 & X(!p3 U p4)))) 3 3 \n", + "23 G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & !p4... 4 0 \n", + "24 G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & !p4 & X((!p... 6 2 \n", + "25 p0 U (p1 & X(p2 U p3)) 3 2 \n", + "26 p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)... 7 2 \n", + "27 F(p0 & XGp1) 2 2 \n", + "28 F(p0 & X(p1 & XFp2)) 4 2 \n", + "29 F(p0 & X(p1 U p2)) 3 1 \n", + ".. ... ... ... \n", + "33 G((p0 & p1 & !p2 & Xp2) -> X(p3 | X(!p1 | p3))) 3 0 \n", + "34 G((p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2... 5 5 \n", + "35 G(p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2 ... 1 1 \n", + "36 G((!p0 & p1) -> Xp2) 2 0 \n", + "37 G(p0 -> X(p0 | p1)) 2 2 \n", + "38 G((!(p1 <-> Xp1) | !(p0 <-> Xp0) | !(p2 <-> Xp... 34 34 \n", + "39 G((p0 & !p1 & Xp1 & Xp0) -> (p2 -> Xp3)) 2 2 \n", + "40 G(p0 -> X(!p0 U p1)) 2 0 \n", + "41 G((!p0 & Xp0) -> X((p0 U p1) | Gp0)) 3 3 \n", + "42 G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1)))) 4 4 \n", + "43 G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1 ... 6 6 \n", + "44 G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ... 6 6 \n", + "45 G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ... 8 8 \n", + "46 G((!p0 & Xp0) -> X(!(!p0 & Xp0) U (!p1 & Xp1))) 6 6 \n", + "47 G(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 ... 12 0 \n", + "48 G((Xp0 -> p0) -> (p1 <-> Xp1)) 4 4 \n", + "49 G((Xp0 -> p0) -> ((p1 -> Xp1) & (!p1 -> X!p1))) 4 4 \n", + "50 p0 & XG!p0 2 1 \n", + "51 XG(p0 -> (G!p1 | (!Xp1 U p2))) 4 1 \n", + "52 XG((p0 & !p1) -> (G!p1 | (!p1 U p2))) 3 2 \n", + "53 XG((p0 & p1) -> (Gp1 | (p1 U p2))) 3 2 \n", + "54 Xp0 & G((!p0 & Xp0) -> XXp0) 5 0 \n", + "55 (Xp0 U Xp1) | !X(p0 U p1) 1 1 \n", + "56 (Xp0 U p1) | !X(p0 U (p0 & p1)) 1 1 \n", + "57 ((Xp0 U p1) | !X(p0 U (p0 & p1))) & G(p0 -> Fp1) 2 2 \n", + "58 ((Xp0 U Xp1) | !X(p0 U p1)) & G(p0 -> Fp1) 2 2 \n", + "59 !G(p0 -> X(p1 R p2)) 3 1 \n", + "60 (p0 & Xp1) R X(((p2 U p3) R p0) U (p2 R p0)) 5 3 \n", + "61 G(p0 | XGp1) & G(p2 | XG!p1) 3 2 \n", + "62 G(p0 | (Xp1 & X!p1)) 1 1 \n", + "\n", + " fwd_closed \n", + "0 True \n", + "1 True \n", + "2 True \n", + "3 True \n", + "4 True \n", + "5 True \n", + "6 True \n", + "7 True \n", + "8 True \n", + "9 True \n", + "10 True \n", + "11 True \n", + "12 True \n", + "13 True \n", + "14 True \n", + "15 True \n", + "16 True \n", + "17 True \n", + "18 True \n", + "19 True \n", + "20 True \n", + "21 True \n", + "22 True \n", + "23 True \n", + "24 True \n", + "25 True \n", + "26 True \n", + "27 True \n", + "28 True \n", + "29 True \n", + ".. ... \n", + "33 True \n", + "34 True \n", + "35 True \n", + "36 True \n", + "37 True \n", + "38 True \n", + "39 True \n", + "40 True \n", + "41 True \n", + "42 True \n", + "43 True \n", + "44 True \n", + "45 True \n", + "46 True \n", + "47 True \n", + "48 True \n", + "49 True \n", + "50 True \n", + "51 True \n", + "52 True \n", + "53 True \n", + "54 True \n", + "55 True \n", + "56 True \n", + "57 True \n", + "58 True \n", + "59 True \n", + "60 True \n", + "61 True \n", + "62 True \n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Let's consider the LTL formula from the following 5 sources,\n", + "# and restrict ourselves to formulas that are not stutter-invariant.\n", + "formulas = [ f for f in gen.ltl_patterns(gen.LTL_DAC_PATTERNS, \n", + " gen.LTL_EH_PATTERNS, \n", + " gen.LTL_HKRSS_PATTERNS, \n", + " gen.LTL_P_PATTERNS, \n", + " gen.LTL_SB_PATTERNS)\n", + " if not f.is_syntactic_stutter_invariant() ]\n", + "\n", + "fmt_txt = []\n", + "aut_size = []\n", + "sistates_size = []\n", + "fwd_closed = []\n", + "\n", + "for f in formulas:\n", + " fmt_txt.append(f.to_str())\n", + " aut = spot.translate(f)\n", + " aut_size.append(aut.num_states())\n", + " sistates = spot.stutter_invariant_states(aut, f)\n", + " sistates_size.append(sum(sistates))\n", + " fwd_closed.append(spot.is_stutter_invariant_forward_closed(aut, sistates) == -1)\n", + " \n", + "# Put everything in a data frame for display.\n", + "df = pandas.DataFrame({'formula': fmt_txt, 'states': aut_size, 'SIstates': sistates_size, 'fwd_closed': fwd_closed},\n", + " columns=['formula','states','SIstates','fwd_closed'])\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is no instance of set of stutter-invariant states that is not closed in these example formulas." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(63, 63)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(fwd_closed), len(fwd_closed)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the percentage of stutter-invarant states." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "55.90277777777778" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "100*sum(sistates_size)/sum(aut_size)" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,2795 +2827,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4rc1" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "spot.setup(show_default='.ban')\n", - "from IPython.display import display" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Stutter-invariant languages\n", - "\n", - "A language $L$ is said to be _stutter-invariant_ iff $\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_{i+1}\\ldots\\in L \\iff \\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_i\\ell_{i+1}\\ldots\\in L$, i.e., if duplicating a letter in a word or removing a duplicated letter does not change the membership of that word to $L$. These languages are also called _stutter-insensitive_. We use the adjective _sutter-sensitive_ to describe a language that is not stutter-invariant. Of course we can extend this vocabulary to LTL formulas or automata that represent stutter-invariant languages.\n", - "\n", - "Stutter-invariant languages play an important role in model checking. When verifying a stutter-invariant specification against a system, we know that we have some freedom in how we discretize the time in the model: as long as we do not hide changes of model variables that are observed by the specification, we can merge multiple steps of the model. This, combined by careful analysis of actions of the model that are independent, is the basis for a set of techniques known as _partial-order reductions_ (POR) that postpone the visit of some successors in the model, because we know we can always visit them later." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Stutter-invariant formulas\n", - "\n", - "When the specification is expressed as an LTL formula, a well known way to ensure it is _stutter-invariant_ is to forbid the use of the `X` operator. Testing whether a formula is `X`-free can be done in constant time using the `is_syntactic_stutter_invariant()` method." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('a U b')\n", - "print(f.is_syntactic_stutter_invariant())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "True\n" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('a U Xb')\n", - "print(f.is_syntactic_stutter_invariant())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "False\n" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However some formula are syntactic-invariant despite their use of `X`. Spot implements some [automaton-based check](https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf) to detect stutter-invariance reliably and efficiently. This can be tested with the `is_stutter_invariant()` function." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = spot.formula('F(a & X(!a & Gb))')\n", - "print(g.is_syntactic_stutter_invariant())\n", - "print(spot.is_stutter_invariant(g))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "False\n", - "True\n" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course this `is_stutter_invariant()` function first checks whether the formula is `X`-free before wasting time building automata, so if you want to detect stutter-invariant formulas in your model checker, this is the only function to use. Also, if you hapen to already have an automaton `aut_g` for `g`, you should pass it as a second argument to avoid it being recomputed: `spot.is_stutter_invariant(g, aut_g)`." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is also known that any stutter-invariant LTL formula can be converted to an `X`-free LTL formula. Several proofs of that exist. Spot implements the rewriting of [K. Etessami](http://homepages.inf.ed.ac.uk/kousha/note_on_stut_tl_lpi.ps) under the name `remove_x()`. Note that the output of this function is only equivalent to its input if the latter is stutter-invariant." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.remove_x(g)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "$\\mathsf{F} (a \\land ((a \\land (a \\mathbin{\\mathsf{U}} (\\lnot a \\land \\mathsf{G} b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} \\lnot a) \\lor (b \\mathbin{\\mathsf{U}} \\lnot a))) \\lor (\\lnot a \\land (\\lnot a \\mathbin{\\mathsf{U}} (a \\land \\lnot a \\land \\mathsf{G} b)) \\land ((\\lnot b \\mathbin{\\mathsf{U}} a) \\lor (b \\mathbin{\\mathsf{U}} a))) \\lor (b \\land (b \\mathbin{\\mathsf{U}} (\\lnot a \\land \\lnot b \\land \\mathsf{G} b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} \\lnot b) \\lor (a \\mathbin{\\mathsf{U}} \\lnot b))) \\lor (\\lnot b \\land (\\lnot b \\mathbin{\\mathsf{U}} (\\lnot a \\land b \\land \\mathsf{G} b)) \\land ((\\lnot a \\mathbin{\\mathsf{U}} b) \\lor (a \\mathbin{\\mathsf{U}} b))) \\lor (\\lnot a \\land \\mathsf{G} b \\land (\\mathsf{G} \\lnot a \\lor \\mathsf{G} a) \\land (\\mathsf{G} b \\lor \\mathsf{G} \\lnot b))))$" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "F(a & ((a & (a U (!a & Gb)) & ((!b U !a) | (b U !a))) | (!a & (!a U (a & !a & Gb)) & ((!b U a) | (b U a))) | (b & (b U (!a & !b & Gb)) & ((!a U !b) | (a U !b))) | (!b & (!b U (!a & b & Gb)) & ((!a U b) | (a U b))) | (!a & Gb & (G!a | Ga) & (Gb | G!b))))" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "Stutter-invariant automata" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly to formulas, automata use a few bits to store some known properties about themselves, like whether they represent a stutter-invariant language. This property can be checked with the `prop_stutter_invariant()` method, but that returns a `trival` instance (i.e., yes, no, or maybe). Some algorithms will update that property whenever that is cheap or expliclitely asked for. For instance `spot.translate()` only sets the property if the translated formula is `X`-free." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate(g)\n", - "print(aut.prop_stutter_invariant())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "maybe\n" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As suggested above, we can call `is_stutter_invariant()` by passing a formula and its automaton, to save on one translation. A second translation is still needed to complement the automaton." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.is_stutter_invariant(g, aut))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "True\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that `prop_stutter_invariant()` was updated as a side-effect so that any futher call to `is_stutter_invariant()` with this automaton will be instantaneous." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(aut.prop_stutter_invariant())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "yes\n" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You have to be aware of this property being set in your back because if while playing with `is_stutter_invariant()` you the incorrect formula for an automaton by mistake, the automaton will have its property set incorrectly, and running `is_stutter_inariant()` with the correct formula will simply return the cached property.\n", - "\n", - "In doubt, you can always reset the property as follows:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut.prop_stutter_invariant(spot.trival_maybe())\n", - "print(aut.prop_stutter_invariant())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "maybe\n" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In case you have an automaton for which you do not have formula, you can also use `is_stutter_invariant()` by passing this automaton as the first argument. In that case a negated automaton will be constructed by determinization. If you do happen to have a negated automaton handy, you can pass it as a second argument to avoid that." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "a1 = spot.automaton('''HOA: v1 \n", - "AP: 1 \"a\" \n", - "States: 2 \n", - "Start: 0 \n", - "Acceptance: 0 t\n", - "--BODY-- \n", - "State: 0 [0] 1 \n", - "State: 1 [t] 0 \n", - "--END--''')\n", - "display(a1)\n", - "print(spot.is_stutter_invariant(a1))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "t\n", - "[all]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce55870> >" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "False\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "heading", - "level": 2, - "metadata": {}, - "source": [ - "Explaining why a formula is not sutter-invariant" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As explained in our [Spin'15 paper](https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf) the sutter-invariant checks are implemented using simple operators suchs as `spot.closure(aut)`, that augment the language of L by adding words that can be obtained by removing duplicated letters, and `spot.sl(aut)` or `spot.sl2(aut)` that both augment the language that L by adding words that can be obtained by duplicating letters. The default `is_stutter_invariant()` function is implemented as `spot.product(spot.closure(aut), spot.closure(neg_aut)).is_empty()`, but that is just one possible implementation selected because it was more efficient.\n", - "\n", - "Using these bricks, we can modify the original algorithm so it uses a counterexample to explain why a formula is stutter-sensitive." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def explain_stut(f):\n", - " f = spot.formula(f)\n", - " pos = spot.translate(f)\n", - " neg = spot.translate(spot.formula_Not(f))\n", - " word = spot.product(spot.closure(pos), spot.closure(neg)).accepting_word()\n", - " if word is None:\n", - " print(f, \"is stutter invariant\")\n", - " return\n", - " word.simplify()\n", - " waut = word.as_automaton()\n", - " if waut.intersects(pos):\n", - " acc, rej, aut = \"accepted\", \"rejected\", neg\n", - " else:\n", - " acc, rej, aut = \"rejected\", \"accepted\", pos\n", - " word2 = spot.sl2(waut).intersecting_word(aut)\n", - " word2.simplify()\n", - " print(\"\"\"{} is {} by {}\n", - " but if we stutter some of its letters, we get\n", - "{} which is {} by {}\"\"\".format(word, acc, f, word2, rej, f))" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "explain_stut('GF(a & Xb)')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "cycle{!a & !b; a & b} is rejected by GF(a & Xb)\n", - " but if we stutter some of its letters, we get\n", - "cycle{!a & !b; a & b; a & b} which is accepted by GF(a & Xb)\n" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Detecting stutter-invariant states\n", - "\n", - "Even if the language of an automaton is not sutter invariant, some of its states may recognize a stutter-invariant language. (We assume the language of a state is the language the automaton would have when starting from this state.)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### First example\n", - "\n", - "For instance let us build a disjunction of a stutter-invariant formula and a stutter-sensitive one:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f1 = spot.formula('F(a & X!a & XF(b & X!b & Ga))')\n", - "f2 = spot.formula('F(a & Xa & XXa & G!b)')\n", - "f = spot.formula_Or([f1, f2])\n", - "\n", - "print(spot.is_stutter_invariant(f1))\n", - "print(spot.is_stutter_invariant(f2))\n", - "print(spot.is_stutter_invariant(f))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "True\n", - "False\n", - "False\n" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "pos = spot.translate(f)\n", - "display(pos)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce2e900> >" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While the automaton as a whole is stutter-sensitive, we can see that eventually we will enter a sub-automaton that is stutter-invariant.\n", - "\n", - "The `stutter_invariant_states()` function returns a Boolean vector indiced by the state number. A state is marked as `True` if either its language is stutter-invariant, or if it can only be reached via a stutter-invariant state (see the second example later). As always, the second argument, `f`, can be omitted (pass `None`) if the formula is unknown, or it can be replaced by a negated automaton if it is known. " - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.stutter_invariant_states(pos, f)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "text": [ - "(False, True, False, True, True, True, True, True)" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For convenience, the `highligh_...()` version colors the stutter-invariant states of the automaton for display.\n", - "(That 5 is the color number for red in Spot's hard-coded palette.)" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.highlight_stutter_invariant_states(pos, f, 5)\n", - "display(pos)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "4->7\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "7->7\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "!b\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce2e900> >" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Such a procedure gives us map of where POR can be enabled when model checking using such an automaton." - ] - }, - { - "cell_type": "heading", - "level": 3, - "metadata": {}, - "source": [ - "Second example" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This second example illustrates the fact that a state can be marked if it it not sutter-invariant but appear below a stutter-invariant state. We build our example automaton as the disjuction of the following two stutter-sensitive formulas, whose union is equivalent to the sutter-invariant formula `GF!a`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g1 = spot.formula('GF(a & Xa) & GF!a')\n", - "g2 = spot.formula('!GF(a & Xa) & GF!a')\n", - "g = spot.formula_Or([g1, g2])" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 17 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.is_stutter_invariant(g1))\n", - "print(spot.is_stutter_invariant(g2))\n", - "print(spot.is_stutter_invariant(g))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "False\n", - "False\n", - "True\n" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here are the automata for `g1` and `g2`, note that none of the states are stutter-invariant." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut1 = spot.translate(g1)\n", - "aut1.set_name(str(g1))\n", - "spot.highlight_stutter_invariant_states(aut1, g1, 5)\n", - "display(aut1)\n", - "\n", - "aut2 = spot.translate(g2)\n", - "aut2.set_name(str(g2))\n", - "spot.highlight_stutter_invariant_states(aut2, g2, 5)\n", - "display(aut2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "G(F(a & Xa) & F!a)\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce2e8d0> >" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "FG(!a | X!a)\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2->1\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce61d50> >" - ] - } - ], - "prompt_number": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we build the sum of these two automata. The stutter-invariance check detects that the initial state is stutter-invariant (i.e., the entire language is stutter-invariant) so all states below it are marked despite the fact that the language recognized from these individual states would not be stutter-invariant." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.sum(aut1, aut2)\n", - "# At this point it is unknown if AUT is stutter-invariant\n", - "assert(aut.prop_stutter_invariant().is_maybe())\n", - "spot.highlight_stutter_invariant_states(aut, g, 5)\n", - "display(aut)\n", - "# The stutter_invariant property is set on AUT as a side effect\n", - "# of calling sutter_invariant_states() or any variant of it.\n", - "assert(aut.prop_stutter_invariant().is_true())\n", - "\n", - "print(aut.to_str())" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "(Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")) | Inf(\n", - "\u2777\n", - ")\n", - "[Fin-less 3]\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "I->5\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "5->0\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "5->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "5->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a\n", - "\u2777\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a\n", - "\u2777\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a\n", - "\u2777\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce2ea50> >" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "HOA: v1\n", - "States: 6\n", - "Start: 5\n", - "AP: 1 \"a\"\n", - "Acceptance: 3 (Inf(0)&Inf(1)) | Inf(2)\n", - "properties: trans-labels explicit-labels trans-acc stutter-invariant\n", - "--BODY--\n", - "State: 0\n", - "[!0] 0 {1}\n", - "[0] 0\n", - "[0] 1 {0}\n", - "State: 1\n", - "[0] 0\n", - "[0] 1 {0}\n", - "State: 2\n", - "[t] 2\n", - "[!0] 3\n", - "[0] 4\n", - "State: 3\n", - "[!0] 3 {2}\n", - "[0] 4 {2}\n", - "State: 4\n", - "[!0] 3 {2}\n", - "State: 5\n", - "[!0] 3\n", - "[0] 1\n", - "[0] 4\n", - "[t] 0\n", - "[t] 2\n", - "--END--\n" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Third example\n", - "\n", - "These procedures work regardless of the acceptance condition. Here is an example with co-B\u00fcchi acceptance.\n", - "\n", - "In this case we do not even have a formula to pass as second argument, so the check will perform a complementation by determinization." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.automaton('randaut --seed=30 -Q4 -A\"Fin(0)\" a |')\n", - "spot.highlight_stutter_invariant_states(aut, None, 5)\n", - "display(aut)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Fin(\n", - "\u24ff\n", - ")\n", - "[co-B\u00fcchi]\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce2e960> >" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the negated automaton is already known, it can be passed as second argument (instead of the positive formula) to avoid unnecessary work." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Sutter-invariance at the letter level\n", - "\n", - "Instead of marking each state as stuttering or not, we can list the letters that we can stutter in each state.\n", - "More precisely, a state $q$ is _stutter-invariant for letter $a$_ if the membership to $L(q)$ of any word starting with $a$ is preserved by the operations that duplicate letters or remove duplicates. \n", - "\n", - "$(\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_{i+1}\\ldots\\in L(q) \\land \\ell_0=a) \\iff (\\ell_0\\ldots\\ell_{i-1}\\ell_i\\ell_i\\ell_{i+1}\\ldots\\in L(q)\\land \\ell_0=a)$\n", - "\n", - "Under this definition, we can also say that $q$ is _stutter-invariant_ iff it is _stutter-invariant for any letter_.\n", - "\n", - "For instance consider the following automaton, for which all words that start with $b$ are stutter invariant.\n", - "The initial state may not be declared as stutter-invariant because of words that start with $\\lnot b$." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('(!b&Xa) | Gb')\n", - "pos = spot.translate(f)\n", - "spot.highlight_stutter_invariant_states(pos, f, 5)\n", - "display(pos)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")\n", - "[B\u00fcchi]\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "I->3\n", - "\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "3->0\n", - "\n", - "\n", - "!b\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\u24ff\n", - "\n", - "\n", - "3->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\u24ff\n", - "\n", - "\n", - "0->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79ce55e10> >" - ] - } - ], - "prompt_number": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `stutter_invariant_letters()` functions returns a vector of BDDs indexed by state numbers. The BDD at index $q$ specifies all letters $\\ell$ for which state $q$ would be stuttering. Note that if $q$ is stutter-invariant or reachable from a stutter-invariant state, the associated BDD will be `bddtrue` (printed as `1` below).\n", - "\n", - "This interface is a bit inconveniant to use interactively, due to the fact that we need a `spot.bdd_dict` object to print a BDD." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sil_vec = spot.stutter_invariant_letters(pos, f)\n", - "for q in range(pos.num_states()):\n", - " print(\"sil_vec[{}] =\".format(q), spot.bdd_format_formula(pos.get_dict(), sil_vec[q]))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "sil_vec[0] = 1\n", - "sil_vec[1] = 1\n", - "sil_vec[2] = 1\n", - "sil_vec[3] = b\n" - ] - } - ], - "prompt_number": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The set of stutter-invariant states is not always forward closed\n", - "\n", - "Consider the following automaton, which is a variant of our second example above. \n", - "\n", - "The language accepted from state (2) is `!GF(a & Xa) & GF!a` (this can be simplified to `FG(!a | X!a)`), while the language accepted from state (0) is `GF(a & Xa) & GF!a`. Therefore. the language accepted from state (5) is `a & X(GF!a)`. Since this is equivalent to `a & GF(!a)` state (5) recognizes stutter-invariant language, but as we can see, it is not the case that all states below (5) are also marked. In fact, states (0) can also be reached via states (7) and (6), recognizing respectively `(a & X(a & GF!a)) | (!a & X(!a & GF(a & Xa) & GF!a))` and `!a & GF(a & Xa) & GF!a))`, i.e., two stutter-sentive languages." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "ex1 = spot.automaton(\"\"\"HOA: v1 \n", - "States: 8 Start: 7 AP: 1 \"a\" Acceptance: 2 (Inf(0)&Inf(1))\n", - "--BODY--\n", - "State: 0 [!0] 0 {1} [0] 0 [0] 1 {0}\n", - "State: 1 [0] 0 [0] 1 {0}\n", - "State: 2 [t] 2 [!0] 3 [0] 4\n", - "State: 3 [!0] 3 {0 1} [0] 4 {0 1}\n", - "State: 4 [!0] 3 {0 1}\n", - "State: 5 [0] 0 [0] 2\n", - "State: 6 [!0] 0\n", - "State: 7 [!0] 6 [0] 5\n", - "--END--\"\"\")\n", - "spot.highlight_stutter_invariant_states(ex1,None, 5)\n", - "display(ex1)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "I->7\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "7->5\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "7->6\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "5->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "6->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79cdf1ba0> >" - ] - } - ], - "prompt_number": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This situation can be tested with `spot.is_stutter_invariant_forward_closed()`. The function returns `-1` if the successor of any stutter-invariant state is it is also a stutter-invariant state, otherwise it return the number of one stutter-sensitive state that has a stutter-invariant state as predecessor." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sistates = spot.stutter_invariant_states(ex1)\n", - "spot.is_stutter_invariant_forward_closed(ex1, sistates)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 25, - "text": [ - "0" - ] - } - ], - "prompt_number": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In cases where we prefer to have a forward-closed set of stutter-invariant states, it is always possible to duplicate\n", - "the problematic states. The `make_stutter_invariant_foward_closed_inplace()` modifies the automaton in place, and also returns an updated copie of the vector of stutter-invariant states." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sistates2 = spot.make_stutter_invariant_forward_closed_inplace(ex1, sistates)\n", - "spot.highlight_stutter_invariant_states(ex1, None, 5)\n", - "display(ex1)\n", - "print(sistates2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "Inf(\n", - "\u24ff\n", - ")&Inf(\n", - "\u2776\n", - ")\n", - "[gen. B\u00fcchi 2]\n", - "\n", - "\n", - "7\n", - "\n", - "7\n", - "\n", - "\n", - "I->7\n", - "\n", - "\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "7->5\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "6\n", - "\n", - "6\n", - "\n", - "\n", - "7->6\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "!a\n", - "\u2776\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "1->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "2->4\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "!a\n", - "\u24ff\n", - "\u2776\n", - "\n", - "\n", - "5->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8\n", - "\n", - "8\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "!a\n", - "\u2776\n", - "\n", - "\n", - "8->8\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "9\n", - "\n", - "9\n", - "\n", - "\n", - "8->9\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "6->0\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "9->8\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "9->9\n", - "\n", - "\n", - "a\n", - "\u24ff\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fc79cdf1ba0> >" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(False, False, True, True, True, True, False, False, True, True)\n" - ] - } - ], - "prompt_number": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, state 0 is no longuer a problem." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.is_stutter_invariant_forward_closed(ex1, sistates2)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 27, - "text": [ - "-1" - ] - } - ], - "prompt_number": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's see how infrequently the set of stutter-invarant states is not closed." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot.gen as gen\n", - "\n", - "try:\n", - " import pandas\n", - "except ImportError:\n", - " import sys; sys.exit(77) # Our test suite will skip the rest if Pandas is missing" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 28 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Let's consider the LTL formula from the following 5 sources,\n", - "# and restrict ourselves to formulas that are not stutter-invariant.\n", - "formulas = [ f for f in gen.ltl_patterns(gen.LTL_DAC_PATTERNS, \n", - " gen.LTL_EH_PATTERNS, \n", - " gen.LTL_HKRSS_PATTERNS, \n", - " gen.LTL_P_PATTERNS, \n", - " gen.LTL_SB_PATTERNS)\n", - " if not f.is_syntactic_stutter_invariant() ]\n", - "\n", - "fmt_txt = []\n", - "aut_size = []\n", - "sistates_size = []\n", - "fwd_closed = []\n", - "\n", - "for f in formulas:\n", - " fmt_txt.append(f.to_str())\n", - " aut = spot.translate(f)\n", - " aut_size.append(aut.num_states())\n", - " sistates = spot.stutter_invariant_states(aut, f)\n", - " sistates_size.append(sum(sistates))\n", - " fwd_closed.append(spot.is_stutter_invariant_forward_closed(aut, sistates) == -1)\n", - " \n", - "# Put everything in a data frame for display.\n", - "df = pandas.DataFrame({'formula': fmt_txt, 'states': aut_size, 'SIstates': sistates_size, 'fwd_closed': fwd_closed},\n", - " columns=['formula','states','SIstates','fwd_closed'])\n", - "display(df)" - ], - "language": "python", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
formulastatesSIstatesfwd_closed
0Fp0 -> (!p0 U (!p0 & p1 & X(!p0 U p2)))32True
1Fp0 -> (!p1 U (p0 | (!p1 & p2 & X(!p1 U p3))))43True
2G!p0 | (!p0 U ((p0 & Fp1) -> (!p1 U (!p1 & p2 ...42True
3G((p0 & Fp1) -> (!p2 U (p1 | (!p2 & p3 & X(!p2...41True
4G(p0 -> (Fp1 -> (!p1 U (p2 | (!p1 & p3 & X(!p1...30True
5F(p0 & XFp1) -> (!p0 U p2)32True
6Fp0 -> (!(!p0 & p1 & X(!p0 U (!p0 & p2))) U (p...43True
7G!p0 | (!p0 U (p0 & (F(p1 & XFp2) -> (!p1 U p3...42True
8G((p0 & Fp1) -> (!(!p1 & p2 & X(!p1 U (!p1 & p...41True
9G(p0 -> ((!(!p1 & p2 & X(!p1 U (!p1 & p3))) U ...30True
10G((p0 & XFp1) -> XF(p1 & Fp2))61True
11Fp0 -> (((p1 & X(!p0 U p2)) -> X(!p0 U (p2 & F...62True
12G(p0 -> G((p1 & XFp2) -> X(!p2 U (p2 & Fp3))))50True
13G((p0 & Fp1) -> (((p2 & X(!p1 U p3)) -> X(!p1 ...102True
14G(p0 -> (((p1 & X(!p2 U p3)) -> X(!p2 U (p3 & ...100True
15G(p0 -> F(p1 & XFp2))40True
16Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & X(!p0 U p3))...41True
17G(p0 -> G(p1 -> (p2 & XFp3)))33True
18G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & X(!...40True
19G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & X(!p2 U p4)...62True
20G(p0 -> F(p1 & !p2 & X(!p2 U p3)))40True
21Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & !p3 & X((!p0...41True
22G(p0 -> G(p1 -> (p2 & !p3 & X(!p3 U p4))))33True
23G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & !p4...40True
24G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & !p4 & X((!p...62True
25p0 U (p1 & X(p2 U p3))32True
26p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)...72True
27F(p0 & XGp1)22True
28F(p0 & X(p1 & XFp2))42True
29F(p0 & X(p1 U p2))31True
...............
33G((p0 & p1 & !p2 & Xp2) -> X(p3 | X(!p1 | p3)))30True
34G((p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2...55True
35G(p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2 ...11True
36G((!p0 & p1) -> Xp2)20True
37G(p0 -> X(p0 | p1))22True
38G((!(p1 <-> Xp1) | !(p0 <-> Xp0) | !(p2 <-> Xp...3434True
39G((p0 & !p1 & Xp1 & Xp0) -> (p2 -> Xp3))22True
40G(p0 -> X(!p0 U p1))20True
41G((!p0 & Xp0) -> X((p0 U p1) | Gp0))33True
42G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1))))44True
43G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1 ...66True
44G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ...66True
45G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ...88True
46G((!p0 & Xp0) -> X(!(!p0 & Xp0) U (!p1 & Xp1)))66True
47G(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 ...120True
48G((Xp0 -> p0) -> (p1 <-> Xp1))44True
49G((Xp0 -> p0) -> ((p1 -> Xp1) & (!p1 -> X!p1)))44True
50p0 & XG!p021True
51XG(p0 -> (G!p1 | (!Xp1 U p2)))41True
52XG((p0 & !p1) -> (G!p1 | (!p1 U p2)))32True
53XG((p0 & p1) -> (Gp1 | (p1 U p2)))32True
54Xp0 & G((!p0 & Xp0) -> XXp0)50True
55(Xp0 U Xp1) | !X(p0 U p1)11True
56(Xp0 U p1) | !X(p0 U (p0 & p1))11True
57((Xp0 U p1) | !X(p0 U (p0 & p1))) & G(p0 -> Fp1)22True
58((Xp0 U Xp1) | !X(p0 U p1)) & G(p0 -> Fp1)22True
59!G(p0 -> X(p1 R p2))31True
60(p0 & Xp1) R X(((p2 U p3) R p0) U (p2 R p0))53True
61G(p0 | XGp1) & G(p2 | XG!p1)32True
62G(p0 | (Xp1 & X!p1))11True
\n", - "

63 rows \u00d7 4 columns

\n", - "
" - ], - "metadata": {}, - "output_type": "display_data", - "text": [ - " formula states SIstates \\\n", - "0 Fp0 -> (!p0 U (!p0 & p1 & X(!p0 U p2))) 3 2 \n", - "1 Fp0 -> (!p1 U (p0 | (!p1 & p2 & X(!p1 U p3)))) 4 3 \n", - "2 G!p0 | (!p0 U ((p0 & Fp1) -> (!p1 U (!p1 & p2 ... 4 2 \n", - "3 G((p0 & Fp1) -> (!p2 U (p1 | (!p2 & p3 & X(!p2... 4 1 \n", - "4 G(p0 -> (Fp1 -> (!p1 U (p2 | (!p1 & p3 & X(!p1... 3 0 \n", - "5 F(p0 & XFp1) -> (!p0 U p2) 3 2 \n", - "6 Fp0 -> (!(!p0 & p1 & X(!p0 U (!p0 & p2))) U (p... 4 3 \n", - "7 G!p0 | (!p0 U (p0 & (F(p1 & XFp2) -> (!p1 U p3... 4 2 \n", - "8 G((p0 & Fp1) -> (!(!p1 & p2 & X(!p1 U (!p1 & p... 4 1 \n", - "9 G(p0 -> ((!(!p1 & p2 & X(!p1 U (!p1 & p3))) U ... 3 0 \n", - "10 G((p0 & XFp1) -> XF(p1 & Fp2)) 6 1 \n", - "11 Fp0 -> (((p1 & X(!p0 U p2)) -> X(!p0 U (p2 & F... 6 2 \n", - "12 G(p0 -> G((p1 & XFp2) -> X(!p2 U (p2 & Fp3)))) 5 0 \n", - "13 G((p0 & Fp1) -> (((p2 & X(!p1 U p3)) -> X(!p1 ... 10 2 \n", - "14 G(p0 -> (((p1 & X(!p2 U p3)) -> X(!p2 U (p3 & ... 10 0 \n", - "15 G(p0 -> F(p1 & XFp2)) 4 0 \n", - "16 Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & X(!p0 U p3))... 4 1 \n", - "17 G(p0 -> G(p1 -> (p2 & XFp3))) 3 3 \n", - "18 G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & X(!... 4 0 \n", - "19 G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & X(!p2 U p4)... 6 2 \n", - "20 G(p0 -> F(p1 & !p2 & X(!p2 U p3))) 4 0 \n", - "21 Fp0 -> ((p1 -> (!p0 U (!p0 & p2 & !p3 & X((!p0... 4 1 \n", - "22 G(p0 -> G(p1 -> (p2 & !p3 & X(!p3 U p4)))) 3 3 \n", - "23 G((p0 & Fp1) -> ((p2 -> (!p1 U (!p1 & p3 & !p4... 4 0 \n", - "24 G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & !p4 & X((!p... 6 2 \n", - "25 p0 U (p1 & X(p2 U p3)) 3 2 \n", - "26 p0 U (p1 & X(p2 & F(p3 & XF(p4 & XF(p5 & XFp6)... 7 2 \n", - "27 F(p0 & XGp1) 2 2 \n", - "28 F(p0 & X(p1 & XFp2)) 4 2 \n", - "29 F(p0 & X(p1 U p2)) 3 1 \n", - ".. ... ... ... \n", - "33 G((p0 & p1 & !p2 & Xp2) -> X(p3 | X(!p1 | p3))) 3 0 \n", - "34 G((p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2... 5 5 \n", - "35 G(p0 & p1 & !p2 & Xp2) -> X(X!p1 | (p2 U (!p2 ... 1 1 \n", - "36 G((!p0 & p1) -> Xp2) 2 0 \n", - "37 G(p0 -> X(p0 | p1)) 2 2 \n", - "38 G((!(p1 <-> Xp1) | !(p0 <-> Xp0) | !(p2 <-> Xp... 34 34 \n", - "39 G((p0 & !p1 & Xp1 & Xp0) -> (p2 -> Xp3)) 2 2 \n", - "40 G(p0 -> X(!p0 U p1)) 2 0 \n", - "41 G((!p0 & Xp0) -> X((p0 U p1) | Gp0)) 3 3 \n", - "42 G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1)))) 4 4 \n", - "43 G((!p0 & Xp0) -> X(p0 U (p0 & !p1 & X(p0 & p1 ... 6 6 \n", - "44 G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ... 6 6 \n", - "45 G((p0 & X!p0) -> X(!p0 U (!p0 & !p1 & X(!p0 & ... 8 8 \n", - "46 G((!p0 & Xp0) -> X(!(!p0 & Xp0) U (!p1 & Xp1))) 6 6 \n", - "47 G(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 | X(!p0 ... 12 0 \n", - "48 G((Xp0 -> p0) -> (p1 <-> Xp1)) 4 4 \n", - "49 G((Xp0 -> p0) -> ((p1 -> Xp1) & (!p1 -> X!p1))) 4 4 \n", - "50 p0 & XG!p0 2 1 \n", - "51 XG(p0 -> (G!p1 | (!Xp1 U p2))) 4 1 \n", - "52 XG((p0 & !p1) -> (G!p1 | (!p1 U p2))) 3 2 \n", - "53 XG((p0 & p1) -> (Gp1 | (p1 U p2))) 3 2 \n", - "54 Xp0 & G((!p0 & Xp0) -> XXp0) 5 0 \n", - "55 (Xp0 U Xp1) | !X(p0 U p1) 1 1 \n", - "56 (Xp0 U p1) | !X(p0 U (p0 & p1)) 1 1 \n", - "57 ((Xp0 U p1) | !X(p0 U (p0 & p1))) & G(p0 -> Fp1) 2 2 \n", - "58 ((Xp0 U Xp1) | !X(p0 U p1)) & G(p0 -> Fp1) 2 2 \n", - "59 !G(p0 -> X(p1 R p2)) 3 1 \n", - "60 (p0 & Xp1) R X(((p2 U p3) R p0) U (p2 R p0)) 5 3 \n", - "61 G(p0 | XGp1) & G(p2 | XG!p1) 3 2 \n", - "62 G(p0 | (Xp1 & X!p1)) 1 1 \n", - "\n", - " fwd_closed \n", - "0 True \n", - "1 True \n", - "2 True \n", - "3 True \n", - "4 True \n", - "5 True \n", - "6 True \n", - "7 True \n", - "8 True \n", - "9 True \n", - "10 True \n", - "11 True \n", - "12 True \n", - "13 True \n", - "14 True \n", - "15 True \n", - "16 True \n", - "17 True \n", - "18 True \n", - "19 True \n", - "20 True \n", - "21 True \n", - "22 True \n", - "23 True \n", - "24 True \n", - "25 True \n", - "26 True \n", - "27 True \n", - "28 True \n", - "29 True \n", - ".. ... \n", - "33 True \n", - "34 True \n", - "35 True \n", - "36 True \n", - "37 True \n", - "38 True \n", - "39 True \n", - "40 True \n", - "41 True \n", - "42 True \n", - "43 True \n", - "44 True \n", - "45 True \n", - "46 True \n", - "47 True \n", - "48 True \n", - "49 True \n", - "50 True \n", - "51 True \n", - "52 True \n", - "53 True \n", - "54 True \n", - "55 True \n", - "56 True \n", - "57 True \n", - "58 True \n", - "59 True \n", - "60 True \n", - "61 True \n", - "62 True \n", - "\n", - "[63 rows x 4 columns]" - ] - } - ], - "prompt_number": 29 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is no instance of set of stutter-invariant states that is not closed in these example formulas." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sum(fwd_closed), len(fwd_closed)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 30, - "text": [ - "(63, 63)" - ] - } - ], - "prompt_number": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here is the percentage of stutter-invarant states." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "100*sum(sistates_size)/sum(aut_size)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 31, - "text": [ - "55.90277777777778" - ] - } - ], - "prompt_number": 31 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/testingaut.ipynb b/tests/python/testingaut.ipynb index 1185ceb52..1564c5230 100644 --- a/tests/python/testingaut.ipynb +++ b/tests/python/testingaut.ipynb @@ -1,4 +1,642 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To translate a formula into a Testing Automaton\n", + "\n", + "Start by building a Buchi automaton" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7f99b4744e40> >" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = spot.formula('a U Gb')\n", + "a = f.translate('ba')\n", + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, gather all the atomic proposition in the formula, and create an automaton with changesets" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "init\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0\n", + "!a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3\n", + "\n", + "0\n", + "a & b\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "0\n", + "a & !b\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "1\n", + "a & b\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "1\n", + "!a & b\n", + "\n", + "\n", + "2->6\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "7\n", + "\n", + "\n", + "1\n", + "a & !b\n", + "\n", + "\n", + "2->7\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "8\n", + "\n", + "\n", + "1\n", + "!a & !b\n", + "\n", + "\n", + "2->8\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->7\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "3->8\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "9\n", + "\n", + "0\n", + "!a & !b\n", + "\n", + "\n", + "3->9\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "4->9\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "5->7\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "5->8\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "6->6\n", + "\n", + "\n", + "{}\n", + "\n", + "\n", + "6->7\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "6->8\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "propset = spot.atomic_prop_collect_as_bdd(f, a)\n", + "ta = spot.tgba_to_ta(a, propset, True, True, False, False, True)\n", + "ta.show('.A')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, remove dead states, and remove stuttering transitions (i.e., transitions labeled by `{}`), marking as *livelock accepting* (rectangles) any states from which there exists a an accepting path labeled by `{}`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "init\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0\n", + "!a & b\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3\n", + "\n", + "0\n", + "a & b\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "0\n", + "a & !b\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "1\n", + "a & b\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "1\n", + "!a & b\n", + "\n", + "\n", + "3->6\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "5->6\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "6->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ta = spot.tgba_to_ta(a, propset, True, True, False, False, False)\n", + "ta.show('.A')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, use bisimulation to minimize the number of states." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "init\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "4\n", + "\n", + "1\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "3->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "{a, b}\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "{b}\n", + "\n", + "\n", + "5->5\n", + "\n", + "\n", + "{a}\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spot.minimize_ta(ta).show('.A')" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,644 +654,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from IPython.display import display, HTML\n", - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To translate a formula into a Testing Automaton\n", - "\n", - "Start by building a Buchi automaton" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = spot.formula('a U Gb')\n", - "a = f.translate('ba')\n", - "a" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "0->0\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "1->1\n", - "\n", - "\n", - "b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7f99b4744e40> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Then, gather all the atomic proposition in the formula, and create an automaton with changesets" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "propset = spot.atomic_prop_collect_as_bdd(f, a)\n", - "ta = spot.tgba_to_ta(a, propset, True, True, False, False, True)\n", - "ta.show('.A')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "init\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "0\n", - "!a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3\n", - "\n", - "0\n", - "a & b\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "0\n", - "a & !b\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "1\n", - "a & b\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "6\n", - "\n", - "\n", - "1\n", - "!a & b\n", - "\n", - "\n", - "2->6\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "7\n", - "\n", - "\n", - "1\n", - "a & !b\n", - "\n", - "\n", - "2->7\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "8\n", - "\n", - "\n", - "1\n", - "!a & !b\n", - "\n", - "\n", - "2->8\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->7\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "3->8\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "9\n", - "\n", - "0\n", - "!a & !b\n", - "\n", - "\n", - "3->9\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "4->9\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "5->7\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "5->8\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "6->6\n", - "\n", - "\n", - "{}\n", - "\n", - "\n", - "6->7\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "6->8\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Then, remove dead states, and remove stuttering transitions (i.e., transitions labeled by `{}`), marking as *livelock accepting* (rectangles) any states from which there exists a an accepting path labeled by `{}`." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "ta = spot.tgba_to_ta(a, propset, True, True, False, False, False)\n", - "ta.show('.A')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "init\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "0\n", - "!a & b\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3\n", - "\n", - "0\n", - "a & b\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "0\n", - "a & !b\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "1\n", - "a & b\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "6\n", - "\n", - "\n", - "1\n", - "!a & b\n", - "\n", - "\n", - "3->6\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "5->6\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "6->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, use bisimulation to minimize the number of states." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "spot.minimize_ta(ta).show('.A')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "svg": [ - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "init\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "a & b\n", - "\n", - "\n", - "4\n", - "\n", - "1\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "a & !b\n", - "\n", - "\n", - "5\n", - "\n", - "\n", - "4\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "3->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "{a, b}\n", - "\n", - "\n", - "4->3\n", - "\n", - "\n", - "{b}\n", - "\n", - "\n", - "5->5\n", - "\n", - "\n", - "{a}\n", - "\n", - "\n", - "" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 5 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tests/python/word.ipynb b/tests/python/word.ipynb index 4bc52263c..d52e54964 100644 --- a/tests/python/word.ipynb +++ b/tests/python/word.ipynb @@ -1,4 +1,709 @@ { + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import spot\n", + "spot.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's build a small automaton to use as example." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "1->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "5\n", + "\n", + "5\n", + "\n", + "\n", + "2->5\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "3->2\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "5->4\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb74c39da80> >" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut = spot.translate('!a & G(Fa <-> XXb)'); aut" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Build an accepting run:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Prefix:\n", + " 0\n", + " | !a\n", + " 1\n", + " | a\n", + "Cycle:\n", + " 2\n", + " | a & b\t{0}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run = aut.accepting_run(); run" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accessing the contents of the run can be done via the `prefix` and `cycle` lists." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "!a\n", + "{0}\n" + ] + } + ], + "source": [ + "print(spot.bdd_format_formula(aut.get_dict(), run.prefix[0].label))\n", + "print(run.cycle[0].acc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To convert the run into a word, using `spot.twa_word()`. Note that our runs are labeled by Boolean formulas that are not necessarily a conjunction of all involved litterals. The word is just the projection of the run on its labels." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "!a; a; cycle{a & b}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "word = spot.twa_word(run); word" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A word can be represented as a collection of signals (one for each atomic proposition). The cycle part is shown twice." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "abprefixcycle\n", + "cycle" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "word.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accessing the different formulas (stored as BDDs) can be done again via the `prefix` and `cycle` lists." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "!a\n", + "a\n", + "a & b\n" + ] + } + ], + "source": [ + "print(spot.bdd_format_formula(aut.get_dict(), word.prefix[0]))\n", + "print(spot.bdd_format_formula(aut.get_dict(), word.prefix[1]))\n", + "print(spot.bdd_format_formula(aut.get_dict(), word.cycle[0]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calling `simplifify()` will produce a shorter word that is compatible with the original word. For instance in the above word, the initial `a` is compatible with both `a & b` and `a & !b`. The word obtained by restricting `a` to `a & b` is therefore still accepted, allowing us to remove the prefix." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "!a; cycle{a & b}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "word.simplify()\n", + "word" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Such a simplified word can be created directly from the automaton:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "!a; cycle{a & b}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aut.accepting_word()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Words can be created using the `parse_word` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a; b; cycle{a & b}\n", + "cycle{(a & bb) | (aaa & bac) | (bac & bbb)}\n", + "a; b; b; qiwuei; \"a;b&c;a\"; cycle{a}\n" + ] + } + ], + "source": [ + "print(spot.parse_word('a; b; cycle{a&b}'))\n", + "print(spot.parse_word('cycle{a&bb|bac&(aaa|bbb)}'))\n", + "print(spot.parse_word('a; b;b; qiwuei;\"a;b&c;a\" ;cycle{a}'))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "a; a & b; cycle{!a & !b; !a & b}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# make sure that we can parse a word back after it has been printed\n", + "w = spot.parse_word(str(spot.parse_word('a;b&a;cycle{!a&!b;!a&b}'))); w" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "abprefixcycle\n", + "cycle" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Words can be easily converted as automata" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w1 = spot.parse_word('a; !a; cycle{a; !a; a}')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "3\n", + "\n", + "3\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "4\n", + "\n", + "4\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fb74c39d990> >" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w1.as_automaton()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The rest of this page tests some syntax errors, you (humans) may skip it, but the test suite will not." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "\n>>> a; b&!a; b\n ^\nA twa_word must contain a cycle\n ()", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; b&!a; b\n ^\nA twa_word must contain a cycle\n\n" + ] + } + ], + "source": [ + "print(spot.parse_word('a; b&!a; b'))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "\n>>> a; b; c}\n ^\nExpected ';' delimiter: '}' stands for ending a cycle\n ()", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; b; c}\n ^\nExpected ';' delimiter: '}' stands for ending a cycle\n\n" + ] + } + ], + "source": [ + "print(spot.parse_word('a; b; c}'))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "\n>>> a; cycle{}\n ^\nempty input\n\n ()", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; cycle{}\n ^\nempty input\n\n\n" + ] + } + ], + "source": [ + "print(spot.parse_word('a; cycle{}'))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "\n>>> a; cycle{!a}; a\n ^\nInput should be finished after cycle\n ()", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; cycle{!a}; a\n ^\nInput should be finished after cycle\n\n" + ] + } + ], + "source": [ + "print(spot.parse_word('a; cycle{!a}; a'))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Creating an empty word is OK...\n", + "w = spot.twa_word(spot._bdd_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "RuntimeError", + "evalue": "a twa_word may not have an empty cycle", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# ... as long as this word is not printed.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/adl/git/spot/python/spot/impl.py\u001b[0m in \u001b[0;36m__str__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 4922\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4923\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0;34m\"std::string\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4924\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_impl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtwa_word___str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4925\u001b[0m \u001b[0mtwa_word_swigregister\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_impl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtwa_word_swigregister\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4926\u001b[0m \u001b[0mtwa_word_swigregister\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtwa_word\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRuntimeError\u001b[0m: a twa_word may not have an empty cycle" + ] + } + ], + "source": [ + "# ... as long as this word is not printed.\n", + "print(w)" + ] + } + ], "metadata": { "kernelspec": { "display_name": "Python 3", @@ -16,701 +721,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" - }, - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import spot\n", - "spot.setup()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's build a small automaton to use as example." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut = spot.translate('!a & G(Fa <-> XXb)'); aut" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 2, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "1->3\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "1->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "2->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "5\n", - "\n", - "5\n", - "\n", - "\n", - "2->5\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "3->2\n", - "\n", - "\n", - "a & b\n", - "\u24ff\n", - "\n", - "\n", - "3->3\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "4->4\n", - "\n", - "\n", - "!a & !b\n", - "\u24ff\n", - "\n", - "\n", - "5->4\n", - "\n", - "\n", - "!a & b\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb74c39da80> >" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Build an accepting run:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "run = aut.accepting_run(); run" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 3, - "text": [ - "Prefix:\n", - " 0\n", - " | !a\n", - " 1\n", - " | a\n", - "Cycle:\n", - " 2\n", - " | a & b\t{0}" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Accessing the contents of the run can be done via the `prefix` and `cycle` lists." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.bdd_format_formula(aut.get_dict(), run.prefix[0].label))\n", - "print(run.cycle[0].acc)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "!a\n", - "{0}\n" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To convert the run into a word, using `spot.twa_word()`. Note that our runs are labeled by Boolean formulas that are not necessarily a conjunction of all involved litterals. The word is just the projection of the run on its labels." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "word = spot.twa_word(run); word" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "!a; a; cycle{a & b}" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A word can be represented as a collection of signals (one for each atomic proposition). The cycle part is shown twice." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "word.show()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "abprefixcycle\n", - "cycle" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Accessing the different formulas (stored as BDDs) can be done again via the `prefix` and `cycle` lists." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.bdd_format_formula(aut.get_dict(), word.prefix[0]))\n", - "print(spot.bdd_format_formula(aut.get_dict(), word.prefix[1]))\n", - "print(spot.bdd_format_formula(aut.get_dict(), word.cycle[0]))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "!a\n", - "a\n", - "a & b\n" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calling `simplifify()` will produce a shorter word that is compatible with the original word. For instance in the above word, the initial `a` is compatible with both `a & b` and `a & !b`. The word obtained by restricting `a` to `a & b` is therefore still accepted, allowing us to remove the prefix." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "word.simplify()\n", - "word" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "!a; cycle{a & b}" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Such a simplified word can be created directly from the automaton:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "aut.accepting_word()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "!a; cycle{a & b}" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Words can be created using the `parse_word` function:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.parse_word('a; b; cycle{a&b}'))\n", - "print(spot.parse_word('cycle{a&bb|bac&(aaa|bbb)}'))\n", - "print(spot.parse_word('a; b;b; qiwuei;\"a;b&c;a\" ;cycle{a}'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "a; b; cycle{a & b}\n", - "cycle{(a & bb) | (aaa & bac) | (bac & bbb)}\n", - "a; b; b; qiwuei; \"a;b&c;a\"; cycle{a}\n" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# make sure that we can parse a word back after it has been printed\n", - "w = spot.parse_word(str(spot.parse_word('a;b&a;cycle{!a&!b;!a&b}'))); w" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "text": [ - "a; a & b; cycle{!a & !b; !a & b}" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "w.show()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "abprefixcycle\n", - "cycle" - ], - "text": [ - "" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Words can be easily converted as automata" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "w1 = spot.parse_word('a; !a; cycle{a; !a; a}')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 13 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "w1.as_automaton()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "svg": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "G\n", - "\n", - "\n", - "\n", - "0\n", - "\n", - "0\n", - "\n", - "\n", - "I->0\n", - "\n", - "\n", - "\n", - "\n", - "1\n", - "\n", - "1\n", - "\n", - "\n", - "0->1\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "2\n", - "\n", - "2\n", - "\n", - "\n", - "1->2\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "3\n", - "\n", - "3\n", - "\n", - "\n", - "2->3\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "4\n", - "\n", - "4\n", - "\n", - "\n", - "3->4\n", - "\n", - "\n", - "!a\n", - "\n", - "\n", - "4->2\n", - "\n", - "\n", - "a\n", - "\n", - "\n", - "\n" - ], - "text": [ - " *' at 0x7fb74c39d990> >" - ] - } - ], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The rest of this page tests some syntax errors, you (humans) may skip it, but the test suite will not." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.parse_word('a; b&!a; b'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "\n>>> a; b&!a; b\n ^\nA twa_word must contain a cycle\n ()", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; b&!a; b\n ^\nA twa_word must contain a cycle\n\n" - ] - } - ], - "prompt_number": 15 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.parse_word('a; b; c}'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "\n>>> a; b; c}\n ^\nExpected ';' delimiter: '}' stands for ending a cycle\n ()", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; b; c}\n ^\nExpected ';' delimiter: '}' stands for ending a cycle\n\n" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.parse_word('a; cycle{}'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "\n>>> a; cycle{}\n ^\nempty input\n\n ()", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; cycle{}\n ^\nempty input\n\n\n" - ] - } - ], - "prompt_number": 17 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print(spot.parse_word('a; cycle{!a}; a'))" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "\n>>> a; cycle{!a}; a\n ^\nInput should be finished after cycle\n ()", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32munknown\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m \n>>> a; cycle{!a}; a\n ^\nInput should be finished after cycle\n\n" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Creating an empty word is OK...\n", - "w = spot.twa_word(spot._bdd_dict)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 19 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# ... as long as this word is not printed.\n", - "print(w)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "ename": "RuntimeError", - "evalue": "a twa_word may not have an empty cycle", - "output_type": "pyerr", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# ... as long as this word is not printed.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/adl/git/spot/python/spot/impl.py\u001b[0m in \u001b[0;36m__str__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 4922\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4923\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0;34m\"std::string\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4924\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_impl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtwa_word___str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4925\u001b[0m \u001b[0mtwa_word_swigregister\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_impl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtwa_word_swigregister\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4926\u001b[0m \u001b[0mtwa_word_swigregister\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtwa_word\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mRuntimeError\u001b[0m: a twa_word may not have an empty cycle" - ] - } - ], - "prompt_number": 20 - } - ], - "metadata": {} } - ] + }, + "nbformat": 4, + "nbformat_minor": 2 }