summaryrefslogtreecommitdiff
path: root/integer_sum_from_neighbours/generate-neighborsumsmv.py
blob: 5337219a858199791b2a1c8e322787bce5c75339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/env python
# Usage for 4b (where 100 is the maximum value for the values):
#   $0 100 | nusmv /dev/stdin

import sys

n = 8
maxValue = int(sys.argv[1])
is_b = len(sys.argv) >= 3 and sys.argv[2] == 'b'

def fillin(cases, template_vars):
    if type(cases) == str:
        return cases.format(**template_vars)
    return [template.format(**template_vars) for template in cases]

variables = ["a%d" % i for i in range(1, n+1)]

# vars: a_1 .. a_n
varDefs = " ".join("%s : 0..%d;" % (x, maxValue) for x in variables)

# initial values: a_i = i
initVals = ""
initVals += " & ".join("%s = %d" % (var, i + 1) for i, var in enumerate(variables))

# Transitions:
# - any of the alternatives: sum one, keep others.
trans = "next(a1) = a1 & next(a{n}) = a{n} & (\n".format(n=n)
# The first and last one cannot be changed. In a step, one can choose to
# change a_i for any i, leaving all other j (i != j) intact.
altpreds = []
for i in range(2, n):
    prev = i - 1
    next = i + 1

    # Require a'_i = a_{i-1} + a_{i+1}
    statepreds = fillin([
        "next(a{i}) = a{prev} + a{next}"
    ], vars())

    # Require a'_j = a_j for i != j
    for j in range(2, n):
        if i == j:
            continue
        statepreds += fillin([
            "next(a{j}) = a{j}"
        ], vars())
    altpreds += [
        "(%s)" % " & ".join(statepreds)
    ]
trans += "|\n".join(altpreds)
trans += ")"

# Desired condition
if not is_b:
    spec = "! (a3 = a7)"
else:
    spec = "! (a3 = a5 & a5 = a7)"

# Begin generator
s = """MODULE main
VAR
{varDefs}
INIT
{initVals}
TRANS
{trans}
LTLSPEC G {spec}
""".format(**vars())

try:
    import sys
    print(s)
    # Hack to avoid printing a ugly error in case stdin of next pipe is closed.
    sys.stdout.flush()
    sys.stdout.close()
except BrokenPipeError:
    pass