Created
June 11, 2018 03:22
-
-
Save Lucus16/aa5d7009030e19b8166d261922287686 to your computer and use it in GitHub Desktop.
Horrible Python code that generates horrible NuSMV code to check a horrible elevator specification
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Mstr: | |
def __init__(self, initial=''): | |
if isinstance(initial, Mstr): | |
self.content = initial.content | |
elif isinstance(initial, str): | |
self.content = [initial] | |
elif hasattr(initial, '__iter__'): | |
self.content = [str(x) for x in initial] | |
else: | |
self.content = [str(initial)] | |
def __add__(self, other): | |
if isinstance(other, Mstr): | |
return Mstr([x + y for x in self.content for y in other.content]) | |
else: | |
return Mstr(self + Mstr(other)) | |
def __getitem__(self, i): | |
return self.content[i] | |
def __iter__(self): | |
return iter(self.content) | |
def __str__(self): | |
return ''.join(self.content) | |
def mstr(*args): | |
r = Mstr() | |
for arg in args: | |
r += arg | |
return str(r) | |
n = 10 | |
n_users = 3 | |
varlist = ['doorOpen', 'lightOutside', 'lightInside', 'buttonOutside', | |
'buttonInside', 'atFloor'] | |
varpass = ', '.join(varlist) | |
def joinfs(*args): | |
global n | |
return '\n SPEC (' + ') & ('.join([str(i).join(args) | |
for i in range(n)]) + ')' | |
thing = mstr( | |
'''MODULE main -- elevator | |
VAR | |
atFloor : 0..''', n-1, ';') + \ | |
mstr('\n ', varlist[:5], ' : array 0..', n-1, ' of boolean;') | |
for i in range(n_users): | |
thing += mstr('\n user', i, ' : process user(', varpass, ');') | |
thing += mstr('\n controller : process controller(', varpass, ');') + \ | |
mstr(''' | |
ASSIGN | |
init(atFloor) := ''', str(set(range(n))), ';') + mstr('\n init(', | |
varlist[0:5], '[', range(n), ']) := FALSE;') | |
thing += joinfs('AG(!(atFloor = ', ') -> !doorOpen[', '])') | |
thing += joinfs('AG(buttonInside[', '] -> A[lightInside[', '] U (atFloor = ', | |
' & doorOpen[', '])])') | |
thing += joinfs('AG((atFloor = ', ' & doorOpen[', ']) -> !lightInside[', | |
'])') | |
thing += joinfs('AG((atFloor = ', ' & doorOpen[', ']) -> A[!lightInside[', | |
'] U buttonInside[', ']])') | |
thing += joinfs('AG((buttonInside[', '] & (atFloor = ', ' & doorOpen[', | |
'])) -> lightInside[', '])') | |
thing += joinfs('AG(buttonOutside[', '] -> A[lightOutside[', '] U (atFloor = ', | |
' & doorOpen[', '])])') | |
thing += joinfs('AG((atFloor = ', ' & doorOpen[', ']) -> !lightOutside[', | |
'])') | |
thing += joinfs('AG((atFloor = ', ' & doorOpen[', ']) -> A[!lightOutside[', | |
'] U buttonOutside[', ']])') | |
thing += joinfs('AG((buttonOutside[', '] & (atFloor = ', ' & doorOpen[', | |
'])) -> lightOutside[', '])') | |
thing += joinfs('AG((!lightInside[', '] & !lightOutside[', '] & !(atFloor = ', | |
' & doorOpen[', '])) -> A[!(atFloor = ', ' & doorOpen[', | |
']) U (buttonInside[', '] | buttonOutside[', '])])') | |
thing += joinfs('AG((' + ' & '.join(Mstr('!lightInside[') + range(n) + ']') + | |
' & ' + ' & '.join(Mstr('!lightOutside[') + range(n) + ']') + | |
' & atFloor = ', ') -> A[atFloor = ', ' U (' + | |
' | '.join(Mstr('lightInside[') + range(n) + ']') + ' | ' + | |
' | '.join(Mstr('lightOutside[') + range(n) + ']') + ')])') | |
thing += joinfs('AG(lightInside[', '] -> AF(atFloor = ', ' & doorOpen[', | |
']))') | |
thing += joinfs('AG(lightOutside[', '] -> AF(atFloor = ', ' & doorOpen[', | |
']))') | |
thing += mstr(''' | |
MODULE controller(''', varpass, ''') | |
VAR | |
goingUp : boolean; | |
ASSIGN | |
init(goingUp) := TRUE;''') + \ | |
mstr([mstr('\n next(light', side, '[', i, ']) := (light', side, '[', i, | |
'] | button', side, '[', i, | |
']) & !(atFloor = ', i, ');') | |
for side in ['Outside', 'Inside'] for i in range(n)]) + \ | |
mstr([mstr('\n next(doorOpen[', i, ']) := atFloor = ', i, ' & (lightInside[', | |
i, '] | lightOutside[', i, ']);') for i in range(n)]) + \ | |
mstr(''' | |
next(atFloor) := | |
case''') | |
for going, target, step in [('goingUp', n, 1), ('!goingUp', -1, -1)]: | |
thing += mstr(''' | |
''', going, ''' : | |
case''') | |
for i in range(n): | |
thing += mstr(''' | |
atFloor = ''', i, ''' : | |
case''') | |
for j in range(i, target, step): | |
thing += mstr(''' | |
lightInside[''', j, '] | lightOutside[', j, | |
'] : ', j, ';') | |
thing += mstr(''' | |
TRUE : ''', i, '''; | |
esac;''') | |
thing += mstr(''' | |
esac;''') | |
thing += mstr(''' | |
esac; | |
next(goingUp) := | |
case''') | |
for going, target, step, alt, default in \ | |
[('goingUp', n, 1, n-1, 'FALSE'), ('!goingUp', -1, -1, 0, 'TRUE')]: | |
thing += mstr(''' | |
''', going, ''' : | |
case | |
atFloor = ''', alt, ' : ', default, ';') | |
for i in range(n): | |
if i == alt: continue | |
thing += mstr(''' | |
atFloor = ''', i, ' : ', | |
' | '.join([mstr('lightInside[', j, '] | lightOutside[', j, ']') | |
for j in range(i+step, target, step)]), ';') | |
thing += mstr(''' | |
esac;''') | |
thing += mstr(''' | |
esac; | |
MODULE user(''', varpass, ''') | |
VAR | |
inside : boolean; | |
floor : 0..''', n-1, '''; | |
dest : 0..''', n-1, '''; | |
ASSIGN | |
init(floor) := ''', str(set(range(n))), '''; | |
init(dest) := ''', str(set(range(n))), '''; | |
init(inside) := FALSE;''') | |
for bside, iside, x in [('Outside', '!inside', 'floor'), | |
('Inside', 'inside', 'dest')]: | |
for floor in range(n): | |
thing += mstr(''' | |
next(button''', bside, '[', floor, ']) := ', iside, ' & !light', bside, | |
'[', floor, '] & !(atFloor = ', floor, ' & doorOpen[', floor, | |
']) & ', x, ' = ', floor, ';') | |
thing += mstr(''' | |
next(floor) := | |
case | |
inside : atFloor; | |
!inside : floor; | |
esac; | |
next(dest) := | |
case | |
floor = dest & !inside : ''', str(set(range(n))), '''; | |
TRUE : dest; | |
esac; | |
next(inside) := | |
case | |
atFloor = floor & doorOpen[floor] & !inside & !(floor = dest) : TRUE; | |
atFloor = dest & doorOpen[dest] & inside : FALSE; | |
TRUE : inside; | |
esac;''') | |
print(thing) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment