Franck Pommereau

Merge branch 'andy' of https://forge.ibisc.univ-evry.fr/jdelahous/snakes into andy

#!/usr/bin/env python
import snakes.utils.andy.main as andymain
andymain.main()
# entities: tuple of name of the entities, initial level, tuple of decays 0
# denotes unbounded decay (omega)
# examples:
# entities = ( ('B',4, (0,2,2,2,3)), ('P',0, (0,0)), ('C',0, (0,0)),
# ('G',0, (0,0)) )
# entities = ( ('Sugar',1, (0,2)), ('Aspartame',0, (0,2)),
# ('Glycemia',2, (0,2,2,2)), ('Glucagon',0, (0,2)),
# ('Insulin',0,(0,2,2)) )
entities = ( ('s1',0, (0,1)), ('s2',0, (0,1)), ('s3',0, (0,1)) )
# Activities: Tuple of (activators, inhibitors, results, duration)
# activators, inhibitors are dictionaries of pairs
# (entity, level)
# results are dictionaries of pairs (entity, +z)
# potential activities examples:
# potential = ( (dict([('P',0)]),dict([('P',1)]),dict([('P',1)]),0),
# (dict([('P',1)]),dict(),dict([('P',-1)]),0),
# (dict([('C',0)]),dict([('C',1)]),dict([('C',1)]),0),
# (dict([('C',1)]),dict(),dict([('C',-1)]),0),
# (dict([('G',0)]),dict([('G',1)]),dict([('G',1)]),0),
# (dict([('G',1)]),dict(),dict([('G',-1)]),0) )
# potential = ( (dict([('Sugar',1)]),dict(),
# dict([('Insulin',1),('Glycemia',1)]),0),
# (dict([('Aspartame',1)]),dict(),dict([('Insulin',1)]),0),
# (dict(),dict([('Glycemia',1)]),dict([('Glucagon',1)]),0),
# (dict([('Glycemia',3)]),dict(),dict([('Insulin',1)]),0),
# (dict([('Insulin',2)]),dict(),dict([('Glycemia',-1)]),0),
# (dict([('Insulin',1),('Glycemia',3)]), dict(),
# dict([('Glycemia',-1)]),0),
# (dict([('Insulin',1)]),dict([('Glycemia',2)]),
# dict([('Glycemia',-1)]),0),
# (dict([('Glucagon',1)]),dict(),dict([('Glycemia',+1)]),0)
# )
potential = ( (dict(), dict([('s1',1)]), dict([('s2',1)]), 1),
(dict(), dict([('s2',1)]), dict([('s3',1)]), 1),
(dict(), dict([('s3',1)]), dict([('s1',1)]), 1) )
# obligatory activities examples:
# obligatory = ( (dict([('P',1)]),dict(),dict([('B',1)]),1),
# (dict([('C',1)]),dict(),dict([('B',-1)]),3),
# (dict([('G',1)]),dict(),dict([('B',-2)]),3))
obligatory = ()
"""This package features the Andy compiler, this is mainly a
command-line tool but it can be called also from Python. The API is
very simple and mimics the command line interface
### Function `snakes.utils.andy.main.main` ###
:::python
def main (args=sys.argv[1:]) : ...
Entry point of the compiler
##### Call API #####
* `list args`:
* `return PetriNet`:
##### Exceptions #####
* `DeclarationError`: when
* `CompilationError`: when
"""
# apidoc stop
from snakes import SnakesError
class CompilationError (SnakesError) :
pass
class DeclarationError (SnakesError) :
pass
This diff is collapsed. Click to expand it.
import sys, optparse, os.path, webbrowser
import pdb, traceback
import snakes.plugins
from snakes.utils.andy import CompilationError, DeclarationError
from snakes.utils.andy.simul import Simulator, AndySimulator
from snakes.utils.andy.andy import andy2snakes
from snakes.utils.simul.html import json
##
## error messages
##
options = None
ERR_ARG = 1
ERR_OPT = 2
ERR_IO = 3
ERR_PARSE = 4
ERR_PLUGIN = 5
ERR_COMPILE = 6
ERR_OUTPUT = 7
ERR_BUG = 255
def log (message) :
sys.stdout.write("andy: %s\n" % message.strip())
sys.stdout.flush()
def err (message) :
sys.stderr.write("andy: %s\n" % message.strip())
sys.stderr.flush()
def die (code, message=None) :
global options
if message :
err(message)
if options.debug :
pdb.post_mortem(sys.exc_info()[2])
else :
sys.exit(code)
def bug () :
global options
sys.stderr.write("""
********************************************************************
*** An unexpected error ocurred. Please report this bug to ***
*** <franck.pommereau@gmail.com>, together with the execution ***
*** trace below and, if possible, a stripped-down version of the ***
*** ABCD source code that caused this bug. Thank you for your ***
*** help in improving SNAKES! ***
********************************************************************
""")
traceback.print_exc()
if options.debug :
pdb.post_mortem(sys.exc_info()[2])
else :
sys.exit(ERR_BUG)
##
## options parsing
##
gv_engines = ("dot", "neato", "twopi", "circo", "fdp")
opt = optparse.OptionParser(prog="andy",
usage="%prog [OPTION]... FILE")
opt.add_option("-l", "--load",
dest="plugins", action="append", default=[],
help="load plugin (this option can be repeated)",
metavar="PLUGIN")
opt.add_option("-p", "--pnml",
dest="pnml", action="store", default=None,
help="save net as PNML",
metavar="OUTFILE")
for engine in gv_engines :
opt.add_option("-" + engine[0], "--" + engine,
dest="gv" + engine, action="store", default=None,
help="draw net using '%s' (from GraphViz)" % engine,
metavar="OUTFILE")
opt.add_option("--debug",
dest="debug", action="store_true", default=False,
help="launch debugger on compiler error (default: no)")
opt.add_option("-s", "--simul",
dest="simul", action="store_true", default=False,
help="launch interactive code simulator")
opt.add_option("--headless",
dest="headless", action="store", default=None,
help="headless code simulator, with saved parameters",
metavar="JSONFILE")
opt.add_option("--port",
dest="port", action="store", default=8000, type=int,
help="port on which the simulator server runs",
metavar="PORT")
def getopts (args) :
global options, andy, tmp
(options, args) = opt.parse_args(args)
plugins = []
for p in options.plugins :
plugins.extend(t.strip() for t in p.split(","))
if "labels" not in plugins :
plugins.append("labels")
for engine in gv_engines :
gvopt = getattr(options, "gv%s" % engine)
if gvopt and "gv" not in plugins :
plugins.append("gv")
break
if (options.simul) and "gv" not in plugins :
plugins.append("gv")
options.plugins = plugins
if len(args) < 1 :
err("no input file provided")
opt.print_help()
die(ERR_ARG)
elif len(args) > 1 :
err("more than one input file provided")
opt.print_help()
die(ERR_ARG)
andy = args[0]
if options.pnml == andy :
err("input file also used as output (--pnml)")
opt.print_help()
die(ERR_ARG)
for engine in gv_engines :
if getattr(options, "gv%s" % engine) == andy :
err("input file also used as output (--%s)" % engine)
opt.print_help()
die(ERR_ARG)
##
## drawing nets
##
def draw (net, target, engine="dot") :
try :
return net.draw(target, engine=engine)
except :
die(ERR_OUTPUT, str(sys.exc_info()[1]))
##
## save pnml
##
def save_pnml (net, target) :
try :
out = open(target, "w")
out.write(snk.dumps(net))
out.close()
except :
die(ERR_OUTPUT, str(sys.exc_info()[1]))
##
## simulator (not standalone)
##
def simulate (entities, potential, obligatory, filename='<string>') :
global options, snk
getopts(["--simul", filename])
snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk")
net = andy2snakes(snk, entities, potential, obligatory)
net.label(srcfile=filename, snakes=snk)
return AndySimulator(net)
##
## main
##
def main (args=sys.argv[1:]) :
global options, snk
# get options
try:
getopts(args)
except SystemExit :
raise
except :
die(ERR_OPT, str(sys.exc_info()[1]))
# read andy spec
try:
env = {}
execfile(andy, env)
del env['__builtins__']
except:
die(ERR_IO, "could not read input file %r" % andy)
# compile to net
dirname = os.path.dirname(andy)
if dirname and dirname not in sys.path :
sys.path.append(dirname)
elif "." not in sys.path :
sys.path.append(".")
try :
snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk")
except :
die(ERR_PLUGIN, str(sys.exc_info()[1]))
try:
net = andy2snakes(snk, env['entities'], env['potential'],
env['obligatory'])
except:
bug()
# output
if options.pnml :
save_pnml(net, options.pnml)
for engine in gv_engines :
target = getattr(options, "gv%s" % engine)
if target :
draw(net, target, engine)
trace, lineno = [], None
if options.simul :
try :
simul = Simulator(net, options.port)
except :
bug()
simul.start()
if options.headless :
with open(options.headless, "w") as out :
out.write(json({"res" : "%sr" % simul.url,
"url" : simul.url,
"key" : simul.server.httpd.key,
"host" : "127.0.0.1",
"port" : simul.port}))
else :
webbrowser.open(simul.url)
simul.wait()
elif trace :
if lineno is None :
print("unsafe execution:")
else :
asserts = dict((a.lineno, a) for a in net.label("asserts"))
print("line %s, %r failed:"
% (lineno, asserts[lineno].st.source()))
for trans, mode in trace :
print(" %s %s" % (trans, mode))
return net
if __name__ == "__main__" :
main()
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
<!DOCTYPE html>
<html>
<head>
<link type="text/css" href="r/css/bootstrap-theme.css" rel="stylesheet"/>
<link type="text/css" href="r/css/bootstrap.css" rel="stylesheet"/>
<script src="r/js/jquery.min.js"></script>
<script src="r/js/jquery.periodic.js"></script>
<script src="r/js/bootstrap.min.js"></script>
<script src="r/js/d3.min.js"></script>
<script src="r/js/simulator.js"></script>
<style>
path { stroke: steelblue;
stroke-width: 2;
fill: none; }
line { stroke: black; }
text { font-family: Arial;
font-size: 9pt; }
</style>
</head>
<body>
<header class="navbar navbar-static-top">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse"
data-target="#bs-example-navbar-collapse-6">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="#">Simulation SNAKES</a>
</div>
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-6">
<ul class="nav navbar-nav" id="nav_sim">
<li><a id="ui-reset">Reset Simulation</a></li>
<li><a id="ui-quit">Stop Simulation</a></li>
<li><a id="ui-help">Help</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div>
</nav>
</header>
<!-- model to be simulated -->
%(model)s
<!-- information about the simulator -->
<div aria-hidden="true" aria-labelledby="myModalLabel" class="modal fade"
id="about" role="dialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" class="close"
data-dismiss="modal" type="button">x</button>
<h4 class="modal-title" id="myModalLabel">Petri Net</h4>
</div>
<div class="modal-body">
<p>
<span class="title">Andy simulator is part of the
SNAKES toolkit</span><br />
(C) 2014 Franck Pommereau
</p>
<p>
<a href="http://www.ibisc.univ-evry.fr/~fpommereau/SNAKES"
target="_blank">SNAKES homepage</a>
</p>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal"
type="button">Close</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$.simisc({ "nav":{ "about": { "text": "About",
"attr": { "id":"ui-about",
"data-toggle": "modal",
"data-target": "#about"
} } },
"graph": { "color": { "y":"red",
"x":"blue" } } });
});
</script>
</body>
</html>
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
/*!
* jQuery periodic plugin
*
* Copyright 2010, Tom Anderson
* Dual licensed under the MIT or GPL Version 2 licenses.
*
*/
$.periodic = function (options, callback) {
// if the first argument is a function then assume the options aren't being passed
if (jQuery.isFunction(options)) {
callback = options;
options = {};
}
// Merge passed settings with default values
var settings = jQuery.extend({}, jQuery.periodic.defaults, {
ajax_complete : ajaxComplete,
increment : increment,
reset : reset,
cancel : cancel
}, options);
// bookkeeping variables
settings.cur_period = settings.period;
settings.tid = false;
var prev_ajax_response = '';
run();
// return settings so user can tweak them externally
return settings;
// run (or restart if already running) the looping construct
function run() {
// clear/stop existing timer (multiple calls to run() won't result in multiple timers)
cancel();
// let it rip!
settings.tid = setTimeout(function() {
// set the context (this) for the callback to the settings object
callback.call(settings);
// compute the next value for cur_period
increment();
// queue up the next run
if(settings.tid)
run();
}, settings.cur_period);
}
// utility function for use with ajax calls
function ajaxComplete(xhr, status) {
if (status === 'success' && prev_ajax_response !== xhr.responseText) {
// reset the period whenever the response changes
prev_ajax_response = xhr.responseText;
reset();
}
}
// compute the next delay
function increment() {
settings.cur_period *= settings.decay;
if (settings.cur_period < settings.period) {
// don't let it drop below the minimum
reset();
} else if (settings.cur_period > settings.max_period) {
settings.cur_period = settings.max_period;
if (settings.on_max !== undefined) {
// call the user-supplied callback if we reach max_period
settings.on_max.call(settings);
}
}
}
function reset() {
settings.cur_period = settings.period;
// restart with the new timeout
run();
}
function cancel() {
clearTimeout(settings.tid);
settings.tid = null;
}
// other functions we might want to implement
function pause() {}
function resume() {}
function log() {}
};
jQuery.periodic.defaults = {
period : 4000, // 4 sec.
max_period : 1800000, // 30 min.
decay : 1.5, // time period multiplier
on_max : undefined // called if max_period is reached
};
\ No newline at end of file
This diff is collapsed. Click to expand it.
<div class="container-fluid">
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-10">
<div class="page-header">
<h1><tt>Andy Simulator</tt> <small> powered by SNAKES</small></h1>
</div>
<div class="row">
<h3>Player</h3>
<div id="player">&nbsp;</div>
</div>
<div class="row">
<h3>Modes</h3>
<div id="modes">&nbsp;</div>
</div>
<div class="row">
<h3>Net Graph</h3>
<div id="graph">&nbsp;</div>
</div>
<div class="row">
<div id="trace_zone">&nbsp;</div>
</div>
<div class="row">
<h3>Command Panel</h3>
<div id="Command_center">&nbsp;</div>
</div>
</div>
<div class="col-md-1"></div>
</div>
</div>
from snakes.utils.simul import BaseSimulator, BaseHTTPSimulator
class AndySimulator (BaseSimulator) :
def getstate (self, state) :
ret = BaseSimulator.getstate(self, state)
marking = self.states[state]
ret["variables"] = dict((place, tokens.items()[0])
for place, tokens in marking.items())
ret["groups"] = ["timed", "even", "odd"]
modes = []
for i, (trans, binding) in enumerate(marking.modes) :
if (state + i) % 5 == 0 :
groups = ["timed"]
else :
groups = []
modes.append(
{"state" : state,
"mode" : i,
"html" : "%s (%s)" % (trans.name[7:], binding),
"groups" : groups + ["odd" if (state % 2) else "even"]
})
ret["modes"] = [{"select": "#modes", "items": modes}]
return ret
#class Simulator (BaseHTTPSimulator) :
# def __init__ (self, **system) :
# simul = AndySimulator(**system)
# BaseHTTPSimulator.__init__(self, simulator=simul)
class Simulator (BaseHTTPSimulator) :
def __init__ (self, net, port) :
simul = AndySimulator(net)
BaseHTTPSimulator.__init__(self, net, simulator=simul, port=port)
# def init_model (self) :
# return self.res["model.html"] % self.simul.info
# def init_ui (self) :
# return BaseHTTPSimulator.init_ui(self)[:-1] + [{
# "label" : "Show net",
# "id" : "ui-shownet",
# "href" : "#",
# "script" : "dialog($('#model .petrinet').html())"
# }]