{ "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.4.3+" }, "name": "", "signature": "sha256:f8755e90b26b56799cf6192d76999196f60eefa8307d0d104b73f476904754cc" }, "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 0x7f859c0838a0> >" ] } ], "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 0x7f8595d88f60> >" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Saving the 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 0\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": 6 }, { "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": 7, "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", "\n", "\n", "2->2\n", "\n", "\n", "!b\n", "\u24ff\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", "4->2\n", "\n", "\n", "!a & b\n", "\n", "\n", "4->4\n", "\n", "\n", "a & b\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f8595d88fc0> >" ] } ], "prompt_number": 7 }, { "cell_type": "code", "collapsed": false, "input": [ "r = b.accepting_run(); r" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ "Prefix:\n", " 0\n", " | 1\n", " 1\n", " | !a & !b\n", "Cycle:\n", " 2\n", " | !b\t{0}" ] } ], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "r.highlight(5) # the parameter is a color number" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 9 }, { "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": 10, "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", "\n", "\n", "2->2\n", "\n", "\n", "!b\n", "\u24ff\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", "4->2\n", "\n", "\n", "!a & b\n", "\n", "\n", "4->4\n", "\n", "\n", "a & b\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f8595d88fc0> >" ] } ], "prompt_number": 10 }, { "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 0x7f85a187e090> >" ] }, { "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", "\u24ff\n", "\n", "\n", "0->0\n", "\n", "\n", "!a\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f85a187e060> >" ] } ], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "prod = spot.product(left, right); prod" ], "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", "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", "\u2776\n", "\n", "\n", "0->1\n", "\n", "\n", "!a & b\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\u24ff\n", "\u2776\n", "\n", "\n", "1->1\n", "\n", "\n", "!a\n", "\u24ff\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f8595d88d20> >" ] } ], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "run = prod.accepting_run(); run" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ "Prefix:\n", " 0\n", " | a & b\t{1}\n", "Cycle:\n", " 1\n", " | a\t{0,1}" ] } ], "prompt_number": 13 }, { "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": 14 }, { "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", "\u2776\n", "\n", "\n", "0->1\n", "\n", "\n", "!a & b\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\u24ff\n", "\u2776\n", "\n", "\n", "1->1\n", "\n", "\n", "!a\n", "\u24ff\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f8595d88d20> >" ] }, { "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 0x7f85a187e090> >" ] }, { "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", "\u24ff\n", "\n", "\n", "0->0\n", "\n", "\n", "!a\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f85a187e060> >" ] } ], "prompt_number": 15 }, { "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 0x7f85a187e120> >" ] }, { "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 0x7f85a187e0f0> >" ] }, { "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 0x7f85a187e150> >" ] } ], "prompt_number": 16 }, { "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": 17, "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", "\n", "\n", "2->2\n", "\n", "\n", "!b\n", "\u24ff\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", "4->2\n", "\n", "\n", "!a & b\n", "\n", "\n", "4->4\n", "\n", "\n", "a & b\n", "\n", "\n", "\n" ], "text": [ " *' at 0x7f85a187e240> >" ] } ], "prompt_number": 17 } ], "metadata": {} } ] }