python: add a %%pml magic

Fixes #162.

* python/spot/ltsmin.i: Implement the magic.
* NEWS: Mention it.
* tests/python/ltsmin-pml.ipynb: New file.
* tests/Makefile.am, doc/org/tut.org: Add it.
* tests/python/ipnbdoctest.py: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2016-06-12 12:53:55 +02:00
parent a7e4395f9d
commit 272daf62fc
6 changed files with 564 additions and 14 deletions

5
NEWS
View file

@ -65,6 +65,11 @@ New in spot 2.0.1a (not yet released)
* Bindings for language_containment_checker were added.
* Under IPython the spot.ltsmin modules nows offers a
%%pml magic do define promela models, compile them
with spins, and dynamically load them. This is
akin to the %%dve magic that was already supported.
Documentation:
* A new example page shows how to test the equivalence of

View file

@ -63,8 +63,8 @@ real notebooks instead.
- [[https://spot.lrde.epita.fr/ipynb/decompose.html][=decompose.ipynb=]] illustrates the =decompose_strength()= function
- [[https://spot.lrde.epita.fr/ipynb/testingaut.html][=testingaut.ipynb=]] shows the steps necessary to build a testing
automaton
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-dve.html][=ltsmin-dve.ipynb=]] minimal test for loading a DiVinE model using
the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-dve.html][=ltsmin-dve.ipynb=]] loading a DiVinE model using the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-pml.html][=ltsmin-pml.ipynb=]] loading a Promela model using the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/word.html][=word.ipynb=]] example for the =twa_run= and =twa_word= classes.
- [[https://spot.lrde.epita.fr/ipynb/highlighting.html][=highlighting.ipynb=]] shows how to highlight states or edges in
automata.

View file

@ -106,25 +106,31 @@ class model:
res += '\n';
return res
def require(tool):
def require(*tools):
"""
Exit with status code 77 if the required tool is not installed.
This function is mostly useful in Spot test suite, where 77 is a
code used to indicate that some test should be skipped.
"""
if tool != "divine":
raise ValueError("unsupported argument for require(): " + tool)
import shutil
for tool in tools:
if tool == "divine":
if shutil.which("divine") == None:
print ("divine not available", file=sys.stderr)
print("divine not available", file=sys.stderr)
sys.exit(77)
out = subprocess.check_output(['divine', 'compile',
'--help'], stderr=subprocess.STDOUT)
out = subprocess.check_output(['divine', 'compile', '--help'],
stderr=subprocess.STDOUT)
if b'LTSmin' not in out:
print ("divine available but no support for LTSmin",
print("divine available but no support for LTSmin",
file=sys.stderr)
sys.exit(77)
elif tool == "spins":
if shutil.which("spins") == None:
print("spins not available", file=sys.stderr)
sys.exit(77)
else:
raise ValueError("unsupported argument for require(): " + tool)
# Load IPython specific support if we can.
@ -166,8 +172,36 @@ try:
spot.aux.rm_f(t.name + '.cpp')
spot.aux.rm_f(t.name + '2C')
@magics_class
class EditPML(Magics):
@cell_magic
def pml(self, line, cell):
if not line:
raise ValueError("missing variable name for %%pml")
with tempfile.NamedTemporaryFile(dir='.', suffix='.pml') as t:
t.write(cell.encode('utf-8'))
t.flush()
try:
p = subprocess.Popen(['spins', t.name],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True)
out = p.communicate()
if out[0]:
print(out[0], file=sys.stderr)
ret = p.wait()
if ret:
raise subprocess.CalledProcessError(ret, 'spins')
self.shell.user_ns[line] = load(t.name + '.spins')
finally:
spot.aux.rm_f(t.name + '.spins.c')
spot.aux.rm_f(t.name + '.spins')
ip = get_ipython()
ip.register_magics(EditDVE)
ip.register_magics(EditPML)
except (ImportError, NameError):
pass

View file

@ -297,6 +297,7 @@ TESTS_ipython = \
python/formulas.ipynb \
python/highlighting.ipynb \
python/ltsmin-dve.ipynb \
python/ltsmin-pml.ipynb \
python/piperead.ipynb \
python/product.ipynb \
python/randaut.ipynb \

View file

@ -71,6 +71,10 @@ def sanitize(s):
# normalize graphviz version
s = re.sub(r'Generated by graphviz version.*', 'VERSION', s)
# remove Spins verbose output version
s = re.sub(r'SpinS Promela Compiler.*Compiled C model to .*pml.spins',
'SpinS output', s, flags=re.DOTALL)
# 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.

View file

@ -0,0 +1,506 @@
{
"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:bbe178ef6526ace33fca472e0e20c706861b6b033a70d184f5a219c60812d5b7"
},
"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.0 (5-Feb-2013)\n",
"(C) University of Twente, Formal Methods and Tools group\n",
"\n",
"Start parsing tmplq2ksakk.pml...done\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\n",
"\n",
"Generating DM information ...\n",
"Generating DM information done\n",
"\n",
"Generating guard information ...\n",
" Found 0 / 4 ( 0.0%) !MCE guards.\n",
" Found 3 / 8 ( 37.5%) !IMC guards.\n",
" Found 6 / 6 (100.0%) !NES guards.\n",
" Found 6 / 6 (100.0%) !NDS guards.\n",
" Found 6 / 6 (100.0%) !visibilities.\n",
"Generating guard information done\n",
"\n",
"Written C model to /home/adl/git/spot/tests/python/tmplq2ksakk.pml.spins.c\n",
"Compiled C model to tmplq2ksakk.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",
" _nr_pr: int\n",
" P_0._pc: pc\n",
" P_0._pid: pid\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": [
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Generated by graphviz version 2.38.0 (20140413.2041)\n",
" -->\n",
"<!-- Title: G Pages: 1 -->\n",
"<svg width=\"734pt\" height=\"75pt\"\n",
" viewBox=\"0.00 0.00 734.00 75.07\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g id=\"graph0\" class=\"graph\" transform=\"scale(0.239277 0.239277) rotate(0) translate(4 309.74)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-309.74 3063.57,-309.74 3063.57,4 -4,4\"/>\n",
"<!-- I -->\n",
"<!-- 0 -->\n",
"<g id=\"node2\" class=\"node\"><title>0</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"273.881\" cy=\"-152.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"273.881\" y=\"-156.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=0, P_0.b=0</text>\n",
"<text text-anchor=\"middle\" x=\"273.881\" y=\"-141.67\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- I&#45;&gt;0 -->\n",
"<g id=\"edge1\" class=\"edge\"><title>I&#45;&gt;0</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1.04952,-152.87C1.86795,-152.87 12.7769,-152.87 29.7957,-152.87\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"36.8867,-152.87 29.8867,-156.02 33.3867,-152.87 29.8867,-152.87 29.8867,-152.87 29.8867,-152.87 33.3867,-152.87 29.8867,-149.72 36.8867,-152.87 36.8867,-152.87\"/>\n",
"</g>\n",
"<!-- 1 -->\n",
"<g id=\"node3\" class=\"node\"><title>1</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"783.642\" cy=\"-188.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"783.642\" y=\"-192.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=1, P_0.b=0</text>\n",
"<text text-anchor=\"middle\" x=\"783.642\" y=\"-177.67\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 0&#45;&gt;1 -->\n",
"<g id=\"edge2\" class=\"edge\"><title>0&#45;&gt;1</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M475.197,-167.072C508.083,-169.404 542.225,-171.825 575.278,-174.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"582.314,-174.667 575.109,-177.314 578.823,-174.419 575.331,-174.172 575.331,-174.172 575.331,-174.172 578.823,-174.419 575.554,-171.03 582.314,-174.667 582.314,-174.667\"/>\n",
"</g>\n",
"<!-- 2 -->\n",
"<g id=\"node4\" class=\"node\"><title>2</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"783.642\" cy=\"-116.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"783.642\" y=\"-120.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=0, P_0.b=1</text>\n",
"<text text-anchor=\"middle\" x=\"783.642\" y=\"-105.67\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 0&#45;&gt;2 -->\n",
"<g id=\"edge3\" class=\"edge\"><title>0&#45;&gt;2</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M475.197,-138.668C508.083,-136.336 542.225,-133.915 575.278,-131.572\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"582.314,-131.073 575.554,-134.71 578.823,-131.321 575.331,-131.568 575.331,-131.568 575.331,-131.568 578.823,-131.321 575.109,-128.426 582.314,-131.073 582.314,-131.073\"/>\n",
"</g>\n",
"<!-- 3 -->\n",
"<g id=\"node5\" class=\"node\"><title>3</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1293.4\" cy=\"-224.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-228.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=2, P_0.b=0</text>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-213.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 1&#45;&gt;3 -->\n",
"<g id=\"edge4\" class=\"edge\"><title>1&#45;&gt;3</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M984.959,-203.072C1017.84,-205.404 1051.99,-207.825 1085.04,-210.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1092.08,-210.667 1084.87,-213.314 1088.58,-210.419 1085.09,-210.172 1085.09,-210.172 1085.09,-210.172 1088.58,-210.419 1085.32,-207.03 1092.08,-210.667 1092.08,-210.667\"/>\n",
"</g>\n",
"<!-- 4 -->\n",
"<g id=\"node6\" class=\"node\"><title>4</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1293.4\" cy=\"-152.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-156.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=1, P_0.b=1</text>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-141.67\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 1&#45;&gt;4 -->\n",
"<g id=\"edge5\" class=\"edge\"><title>1&#45;&gt;4</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M984.959,-174.668C1017.84,-172.336 1051.99,-169.915 1085.04,-167.572\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1092.08,-167.073 1085.32,-170.71 1088.58,-167.321 1085.09,-167.568 1085.09,-167.568 1085.09,-167.568 1088.58,-167.321 1084.87,-164.426 1092.08,-167.073 1092.08,-167.073\"/>\n",
"</g>\n",
"<!-- 2&#45;&gt;4 -->\n",
"<g id=\"edge6\" class=\"edge\"><title>2&#45;&gt;4</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M984.959,-131.072C1017.84,-133.404 1051.99,-135.825 1085.04,-138.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1092.08,-138.667 1084.87,-141.314 1088.58,-138.419 1085.09,-138.172 1085.09,-138.172 1085.09,-138.172 1088.58,-138.419 1085.32,-135.03 1092.08,-138.667 1092.08,-138.667\"/>\n",
"</g>\n",
"<!-- 5 -->\n",
"<g id=\"node7\" class=\"node\"><title>5</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1293.4\" cy=\"-80.8701\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-84.6701\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=0, P_0.b=2</text>\n",
"<text text-anchor=\"middle\" x=\"1293.4\" y=\"-69.6701\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 2&#45;&gt;5 -->\n",
"<g id=\"edge7\" class=\"edge\"><title>2&#45;&gt;5</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M984.959,-102.668C1017.84,-100.336 1051.99,-97.9155 1085.04,-95.5721\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1092.08,-95.0732 1085.32,-98.7105 1088.58,-95.3208 1085.09,-95.5684 1085.09,-95.5684 1085.09,-95.5684 1088.58,-95.3208 1084.87,-92.4263 1092.08,-95.0732 1092.08,-95.0732\"/>\n",
"</g>\n",
"<!-- 6 -->\n",
"<g id=\"node8\" class=\"node\"><title>6</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1803.17\" cy=\"-260.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-264.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=3, P_0.b=0</text>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-249.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 3&#45;&gt;6 -->\n",
"<g id=\"edge8\" class=\"edge\"><title>3&#45;&gt;6</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1494.72,-239.072C1527.61,-241.404 1561.75,-243.825 1594.8,-246.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1601.84,-246.667 1594.63,-249.314 1598.35,-246.419 1594.85,-246.172 1594.85,-246.172 1594.85,-246.172 1598.35,-246.419 1595.08,-243.03 1601.84,-246.667 1601.84,-246.667\"/>\n",
"</g>\n",
"<!-- 7 -->\n",
"<g id=\"node9\" class=\"node\"><title>7</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1803.17\" cy=\"-188.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-192.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=2, P_0.b=1</text>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-177.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 3&#45;&gt;7 -->\n",
"<g id=\"edge9\" class=\"edge\"><title>3&#45;&gt;7</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1494.72,-210.668C1527.61,-208.336 1561.75,-205.915 1594.8,-203.572\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1601.84,-203.073 1595.08,-206.71 1598.35,-203.321 1594.85,-203.568 1594.85,-203.568 1594.85,-203.568 1598.35,-203.321 1594.63,-200.426 1601.84,-203.073 1601.84,-203.073\"/>\n",
"</g>\n",
"<!-- 4&#45;&gt;7 -->\n",
"<g id=\"edge10\" class=\"edge\"><title>4&#45;&gt;7</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1494.72,-167.072C1527.61,-169.404 1561.75,-171.825 1594.8,-174.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1601.84,-174.667 1594.63,-177.314 1598.35,-174.419 1594.85,-174.172 1594.85,-174.172 1594.85,-174.172 1598.35,-174.419 1595.08,-171.03 1601.84,-174.667 1601.84,-174.667\"/>\n",
"</g>\n",
"<!-- 8 -->\n",
"<g id=\"node10\" class=\"node\"><title>8</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1803.17\" cy=\"-116.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-120.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=1, P_0.b=2</text>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-105.67\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 4&#45;&gt;8 -->\n",
"<g id=\"edge11\" class=\"edge\"><title>4&#45;&gt;8</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1494.72,-138.668C1527.61,-136.336 1561.75,-133.915 1594.8,-131.572\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1601.84,-131.073 1595.08,-134.71 1598.35,-131.321 1594.85,-131.568 1594.85,-131.568 1594.85,-131.568 1598.35,-131.321 1594.63,-128.426 1601.84,-131.073 1601.84,-131.073\"/>\n",
"</g>\n",
"<!-- 5&#45;&gt;8 -->\n",
"<g id=\"edge12\" class=\"edge\"><title>5&#45;&gt;8</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1494.72,-95.0724C1527.61,-97.404 1561.75,-99.8246 1594.8,-102.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1601.84,-102.667 1594.63,-105.314 1598.35,-102.419 1594.85,-102.172 1594.85,-102.172 1594.85,-102.172 1598.35,-102.419 1595.08,-99.0296 1601.84,-102.667 1601.84,-102.667\"/>\n",
"</g>\n",
"<!-- 9 -->\n",
"<g id=\"node11\" class=\"node\"><title>9</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"1803.17\" cy=\"-26.8701\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-30.6701\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=0, P_0.b=3</text>\n",
"<text text-anchor=\"middle\" x=\"1803.17\" y=\"-15.6701\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 5&#45;&gt;9 -->\n",
"<g id=\"edge13\" class=\"edge\"><title>5&#45;&gt;9</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1467.02,-62.5128C1517.13,-57.1834 1571.96,-51.3518 1622.5,-45.9776\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1629.6,-45.2224 1622.97,-49.0951 1626.12,-45.5926 1622.64,-45.9628 1622.64,-45.9628 1622.64,-45.9628 1626.12,-45.5926 1622.3,-42.8304 1629.6,-45.2224 1629.6,-45.2224\"/>\n",
"</g>\n",
"<!-- 6&#45;&gt;6 -->\n",
"<g id=\"edge14\" class=\"edge\"><title>6&#45;&gt;6</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1709.05,-285.787C1701.35,-296.536 1732.72,-305.74 1803.17,-305.74 1857.1,-305.74 1888.13,-300.345 1896.25,-292.992\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1897.28,-285.787 1899.41,-293.16 1896.78,-289.252 1896.29,-292.717 1896.29,-292.717 1896.29,-292.717 1896.78,-289.252 1893.17,-292.275 1897.28,-285.787 1897.28,-285.787\"/>\n",
"</g>\n",
"<!-- 10 -->\n",
"<g id=\"node12\" class=\"node\"><title>10</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"2312.93\" cy=\"-224.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-228.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=3, P_0.b=1</text>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-213.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; !&quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 7&#45;&gt;10 -->\n",
"<g id=\"edge15\" class=\"edge\"><title>7&#45;&gt;10</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2004.48,-203.072C2037.37,-205.404 2071.51,-207.825 2104.56,-210.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2111.6,-210.667 2104.39,-213.314 2108.11,-210.419 2104.62,-210.172 2104.62,-210.172 2104.62,-210.172 2108.11,-210.419 2104.84,-207.03 2111.6,-210.667 2111.6,-210.667\"/>\n",
"</g>\n",
"<!-- 11 -->\n",
"<g id=\"node13\" class=\"node\"><title>11</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"2312.93\" cy=\"-152.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-156.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=2, P_0.b=2</text>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-141.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; !dead</text>\n",
"</g>\n",
"<!-- 7&#45;&gt;11 -->\n",
"<g id=\"edge16\" class=\"edge\"><title>7&#45;&gt;11</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2004.48,-174.668C2037.37,-172.336 2071.51,-169.915 2104.56,-167.572\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2111.6,-167.073 2104.84,-170.71 2108.11,-167.321 2104.62,-167.568 2104.62,-167.568 2104.62,-167.568 2108.11,-167.321 2104.39,-164.426 2111.6,-167.073 2111.6,-167.073\"/>\n",
"</g>\n",
"<!-- 8&#45;&gt;11 -->\n",
"<g id=\"edge17\" class=\"edge\"><title>8&#45;&gt;11</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2004.48,-131.072C2037.37,-133.404 2071.51,-135.825 2104.56,-138.168\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2111.6,-138.667 2104.39,-141.314 2108.11,-138.419 2104.62,-138.172 2104.62,-138.172 2104.62,-138.172 2108.11,-138.419 2104.84,-135.03 2111.6,-138.667 2111.6,-138.667\"/>\n",
"</g>\n",
"<!-- 12 -->\n",
"<g id=\"node14\" class=\"node\"><title>12</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"2312.93\" cy=\"-62.8701\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-66.6701\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=1, P_0.b=3</text>\n",
"<text text-anchor=\"middle\" x=\"2312.93\" y=\"-51.6701\" font-family=\"Lato\" font-size=\"14.00\">&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 8&#45;&gt;12 -->\n",
"<g id=\"edge18\" class=\"edge\"><title>8&#45;&gt;12</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1976.78,-98.5128C2026.89,-93.1834 2081.73,-87.3518 2132.26,-81.9776\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2139.36,-81.2224 2132.73,-85.0951 2135.88,-81.5926 2132.4,-81.9628 2132.4,-81.9628 2132.4,-81.9628 2135.88,-81.5926 2132.07,-78.8304 2139.36,-81.2224 2139.36,-81.2224\"/>\n",
"</g>\n",
"<!-- 9&#45;&gt;9 -->\n",
"<g id=\"edge19\" class=\"edge\"><title>9&#45;&gt;9</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1709.05,-51.7868C1701.35,-62.5364 1732.72,-71.7401 1803.17,-71.7401 1857.1,-71.7401 1888.13,-66.3451 1896.25,-58.9918\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1897.28,-51.7868 1899.41,-59.1598 1896.78,-55.2521 1896.29,-58.7174 1896.29,-58.7174 1896.29,-58.7174 1896.78,-55.2521 1893.17,-58.2751 1897.28,-51.7868 1897.28,-51.7868\"/>\n",
"</g>\n",
"<!-- 10&#45;&gt;10 -->\n",
"<g id=\"edge20\" class=\"edge\"><title>10&#45;&gt;10</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2218.82,-249.787C2211.11,-260.536 2242.48,-269.74 2312.93,-269.74 2366.86,-269.74 2397.89,-264.345 2406.02,-256.992\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2407.04,-249.787 2409.17,-257.16 2406.55,-253.252 2406.05,-256.717 2406.05,-256.717 2406.05,-256.717 2406.55,-253.252 2402.94,-256.275 2407.04,-249.787 2407.04,-249.787\"/>\n",
"</g>\n",
"<!-- 13 -->\n",
"<g id=\"node15\" class=\"node\"><title>13</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"2822.69\" cy=\"-197.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"2822.69\" y=\"-201.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=3, P_0.b=2</text>\n",
"<text text-anchor=\"middle\" x=\"2822.69\" y=\"-186.67\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 11&#45;&gt;13 -->\n",
"<g id=\"edge21\" class=\"edge\"><title>11&#45;&gt;13</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2500.12,-169.371C2541.94,-173.078 2586.41,-177.019 2628.51,-180.75\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2635.52,-181.371 2628.27,-183.891 2632.04,-181.062 2628.55,-180.753 2628.55,-180.753 2628.55,-180.753 2632.04,-181.062 2628.83,-177.615 2635.52,-181.371 2635.52,-181.371\"/>\n",
"</g>\n",
"<!-- 14 -->\n",
"<g id=\"node16\" class=\"node\"><title>14</title>\n",
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"2822.69\" cy=\"-107.87\" rx=\"236.762\" ry=\"26.7407\"/>\n",
"<text text-anchor=\"middle\" x=\"2822.69\" y=\"-111.67\" font-family=\"Lato\" font-size=\"14.00\">_nr_pr=1, P_0._pc=0, P_0._pid=0, P_0.a=2, P_0.b=3</text>\n",
"<text text-anchor=\"middle\" x=\"2822.69\" y=\"-96.6701\" font-family=\"Lato\" font-size=\"14.00\">!&quot;P_0.a &lt; 2&quot; &amp; &quot;P_0.b &gt; 1&quot; &amp; dead</text>\n",
"</g>\n",
"<!-- 11&#45;&gt;14 -->\n",
"<g id=\"edge22\" class=\"edge\"><title>11&#45;&gt;14</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2500.12,-136.369C2541.94,-132.663 2586.41,-128.721 2628.51,-124.99\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2635.52,-124.369 2628.83,-128.125 2632.04,-124.678 2628.55,-124.987 2628.55,-124.987 2628.55,-124.987 2632.04,-124.678 2628.27,-121.849 2635.52,-124.369 2635.52,-124.369\"/>\n",
"</g>\n",
"<!-- 12&#45;&gt;12 -->\n",
"<g id=\"edge23\" class=\"edge\"><title>12&#45;&gt;12</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2218.82,-87.7868C2211.11,-98.5364 2242.48,-107.74 2312.93,-107.74 2366.86,-107.74 2397.89,-102.345 2406.02,-94.9918\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2407.04,-87.7868 2409.17,-95.1598 2406.55,-91.2521 2406.05,-94.7174 2406.05,-94.7174 2406.05,-94.7174 2406.55,-91.2521 2402.94,-94.2751 2407.04,-87.7868 2407.04,-87.7868\"/>\n",
"</g>\n",
"<!-- 13&#45;&gt;13 -->\n",
"<g id=\"edge24\" class=\"edge\"><title>13&#45;&gt;13</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2728.58,-222.787C2720.87,-233.536 2752.24,-242.74 2822.69,-242.74 2876.62,-242.74 2907.65,-237.345 2915.78,-229.992\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2916.8,-222.787 2918.93,-230.16 2916.31,-226.252 2915.82,-229.717 2915.82,-229.717 2915.82,-229.717 2916.31,-226.252 2912.7,-229.275 2916.8,-222.787 2916.8,-222.787\"/>\n",
"</g>\n",
"<!-- 14&#45;&gt;14 -->\n",
"<g id=\"edge25\" class=\"edge\"><title>14&#45;&gt;14</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2728.58,-132.787C2720.87,-143.536 2752.24,-152.74 2822.69,-152.74 2876.62,-152.74 2907.65,-147.345 2915.78,-139.992\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2916.8,-132.787 2918.93,-140.16 2916.31,-136.252 2915.82,-139.717 2915.82,-139.717 2915.82,-139.717 2916.31,-136.252 2912.7,-139.275 2916.8,-132.787 2916.8,-132.787\"/>\n",
"</g>\n",
"</g>\n",
"</svg>\n"
],
"text": [
"<spot.impl.kripke; proxy of <Swig Object of type 'std::shared_ptr< spot::kripke > *' at 0x7f87ac090240> >"
]
}
],
"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",
" _nr_pr: int\n",
" P_0._pc: pc\n",
" P_0._pid: pid\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": {}
}
]
}