{ "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.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": {} } ] }