umaudemc 0.12.1__py3-none-any.whl → 0.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umaudemc/__init__.py +1 -1
- umaudemc/__main__.py +7 -1
- umaudemc/api.py +3 -3
- umaudemc/backend/_spot.py +7 -8
- umaudemc/backend/bmcalc.py +8 -8
- umaudemc/backend/ltsmin.py +1 -1
- umaudemc/backend/nusmv.py +1 -1
- umaudemc/backend/prism.py +3 -3
- umaudemc/backend/spin.py +1 -1
- umaudemc/command/acheck.py +21 -0
- umaudemc/command/graph.py +31 -3
- umaudemc/command/scheck.py +1 -1
- umaudemc/command/test.py +28 -10
- umaudemc/common.py +0 -24
- umaudemc/counterprint.py +12 -4
- umaudemc/data/smcgraph.js +3 -0
- umaudemc/data/smcview.js +42 -29
- umaudemc/formatter.py +20 -25
- umaudemc/formulae.py +4 -4
- umaudemc/grapher.py +6 -5
- umaudemc/gtk.py +88 -499
- umaudemc/kleene.py +156 -0
- umaudemc/mproc.py +1 -1
- umaudemc/opsem.py +1 -1
- umaudemc/probabilistic.py +13 -10
- umaudemc/pyslang.py +320 -186
- umaudemc/quatex.py +3 -3
- umaudemc/resources.py +25 -9
- umaudemc/webui.py +37 -34
- umaudemc/wrappers.py +44 -2
- {umaudemc-0.12.1.dist-info → umaudemc-0.13.0.dist-info}/METADATA +6 -7
- umaudemc-0.13.0.dist-info/RECORD +59 -0
- {umaudemc-0.12.1.dist-info → umaudemc-0.13.0.dist-info}/WHEEL +1 -1
- umaudemc-0.12.1.dist-info/RECORD +0 -57
- {umaudemc-0.12.1.dist-info → umaudemc-0.13.0.dist-info}/LICENSE +0 -0
- {umaudemc-0.12.1.dist-info → umaudemc-0.13.0.dist-info}/entry_points.txt +0 -0
- {umaudemc-0.12.1.dist-info → umaudemc-0.13.0.dist-info}/top_level.txt +0 -0
umaudemc/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.12.
|
|
1
|
+
__version__ = '0.12.2'
|
umaudemc/__main__.py
CHANGED
|
@@ -62,7 +62,8 @@ def add_backend_arg(parser):
|
|
|
62
62
|
|
|
63
63
|
parser.add_argument(
|
|
64
64
|
'--backend',
|
|
65
|
-
help='comma-separated prioritized list of model-checking backends
|
|
65
|
+
help='comma-separated prioritized list of model-checking backends '
|
|
66
|
+
'(among maude, ltsmin, pymc, nusmv, spot, spin, builtin)'
|
|
66
67
|
)
|
|
67
68
|
|
|
68
69
|
|
|
@@ -205,6 +206,11 @@ def build_parser():
|
|
|
205
206
|
help='probability assignment method for adding them to the graph',
|
|
206
207
|
metavar='METHOD'
|
|
207
208
|
)
|
|
209
|
+
parser_graph.add_argument(
|
|
210
|
+
'-k', '--kleene-iteration',
|
|
211
|
+
help='write annotations on the transitions starting and terminating an iteration',
|
|
212
|
+
action='store_true'
|
|
213
|
+
)
|
|
208
214
|
parser_graph.set_defaults(mode='graph')
|
|
209
215
|
|
|
210
216
|
#
|
umaudemc/api.py
CHANGED
|
@@ -215,7 +215,7 @@ class MaudeModel:
|
|
|
215
215
|
:type merge_states: str
|
|
216
216
|
:param backends: Prioritized list of model checking backends to be used
|
|
217
217
|
:type backends: str or list of str
|
|
218
|
-
:param formula_str: Formula given a
|
|
218
|
+
:param formula_str: Formula given a string (in case formula is a list)
|
|
219
219
|
:type formula_str: str or None
|
|
220
220
|
:param logic: Logic (in case formula is a list)
|
|
221
221
|
:type logic: str
|
|
@@ -297,7 +297,7 @@ class MaudeModel:
|
|
|
297
297
|
wgraph = _wrappers.BoundedGraph(self.graph, depth) if depth > 0 else self.graph
|
|
298
298
|
|
|
299
299
|
# Create and store the wrapped graph
|
|
300
|
-
wgraph = _wrappers.
|
|
300
|
+
wgraph = _wrappers.wrap_graph(wgraph, purge, merge)
|
|
301
301
|
self.wgraphs[(purge, merge, depth > 0)] = wgraph
|
|
302
302
|
|
|
303
303
|
# In case both purge and merge are used, we keep the purged
|
|
@@ -517,7 +517,7 @@ class MaudeModel:
|
|
|
517
517
|
|
|
518
518
|
def print_counterexample(self, stats, printer=None, sformat=None, eformat=None):
|
|
519
519
|
"""
|
|
520
|
-
Pretty print
|
|
520
|
+
Pretty print a counterexample for a previous check (nothing is printed
|
|
521
521
|
if no counterexample has been found)
|
|
522
522
|
|
|
523
523
|
:param stats: Statistics produced by the check method
|
umaudemc/backend/_spot.py
CHANGED
|
@@ -8,7 +8,6 @@ import buddy
|
|
|
8
8
|
import spot
|
|
9
9
|
|
|
10
10
|
from ..formulae import collect_aprops
|
|
11
|
-
from ..opsem import OpSemKleeneInstance, OpSemGraph
|
|
12
11
|
from ..wrappers import create_graph
|
|
13
12
|
|
|
14
13
|
|
|
@@ -136,9 +135,10 @@ class KleeneModelBuilder(SpotModelBuilder):
|
|
|
136
135
|
"""Generator of ω-automata for strategy-controlled models with an iteration like the Kleene star"""
|
|
137
136
|
|
|
138
137
|
def __init__(self, module, initial, strategy, aprops, bdd_dict, metamodule=None, opaques=()):
|
|
139
|
-
|
|
138
|
+
from ..kleene import get_kleene_graph_mts
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
# opaque strategies are ignored with the new implementation
|
|
141
|
+
super().__init__(get_kleene_graph_mts(module, initial, strategy), aprops, bdd_dict)
|
|
142
142
|
|
|
143
143
|
# Table of distinct iterations (from their context to the index of
|
|
144
144
|
# its accepting condition)
|
|
@@ -166,7 +166,7 @@ class KleeneModelBuilder(SpotModelBuilder):
|
|
|
166
166
|
state = pending.pop()
|
|
167
167
|
state_spot = self.state_map[state]
|
|
168
168
|
|
|
169
|
-
for next_state in self.graph.
|
|
169
|
+
for next_state, edge in self.graph.getTransitions(state):
|
|
170
170
|
next_state_spot = self.state_map.get(next_state)
|
|
171
171
|
|
|
172
172
|
if next_state_spot is None:
|
|
@@ -175,10 +175,10 @@ class KleeneModelBuilder(SpotModelBuilder):
|
|
|
175
175
|
pending.append(next_state)
|
|
176
176
|
|
|
177
177
|
# Check the iteration tags and set the accepting labels of the edges
|
|
178
|
-
next_state_term = self.
|
|
178
|
+
next_state_term = self.graph.getStateTerm(next_state)
|
|
179
179
|
acc_set = []
|
|
180
180
|
|
|
181
|
-
for tag, enter in
|
|
181
|
+
for tag, enter in edge.iterations:
|
|
182
182
|
acc_index = self.iter_map.get(tag)
|
|
183
183
|
|
|
184
184
|
if acc_index is None:
|
|
@@ -299,7 +299,6 @@ class SpotBackend:
|
|
|
299
299
|
stats['counterexample'] = model_builder.extract_counterexample(run, model_automaton)
|
|
300
300
|
|
|
301
301
|
if get_graph:
|
|
302
|
-
stats['graph'] = model_builder.graph
|
|
303
|
-
else OpSemGraph(model_builder.graph, model_builder.instance)
|
|
302
|
+
stats['graph'] = model_builder.graph
|
|
304
303
|
|
|
305
304
|
return holds, stats
|
umaudemc/backend/bmcalc.py
CHANGED
|
@@ -85,21 +85,21 @@ class ParityGame:
|
|
|
85
85
|
|
|
86
86
|
# The recursive Zielonka's algorithm implemented in solve_rec does not
|
|
87
87
|
# take finite plays into account, which are handled here. The recursive
|
|
88
|
-
# algorithm receives a
|
|
88
|
+
# algorithm receives a game without deadlock states.
|
|
89
89
|
# (this decomposition is sound, because if player i can force the game
|
|
90
90
|
# to reach a deadlock state for 1-i, player 1-i cannot force reaching a
|
|
91
91
|
# deadlock state for i nor an infinite play)
|
|
92
92
|
w0, w1 = self.solve_rec(whole_game - finite_win0 - finite_win1)
|
|
93
93
|
|
|
94
|
-
# The winning states for each player are the union of those in which
|
|
95
|
-
#
|
|
94
|
+
# The winning states for each player are the union of those in which they
|
|
95
|
+
# have an infinite and those in which they have a finite winning strategy
|
|
96
96
|
return w0.union(finite_win0), w1.union(finite_win1)
|
|
97
97
|
|
|
98
98
|
def attractor(self, player, subgame, subset):
|
|
99
99
|
"""Compute the attractor of a subset on a subgraph for a player"""
|
|
100
100
|
|
|
101
|
-
# Iteratively extend subset with the states where it is
|
|
102
|
-
# the given player can reach the previous subset.
|
|
101
|
+
# Iteratively extend subset with the states where it is certain
|
|
102
|
+
# that the given player can reach the previous subset.
|
|
103
103
|
|
|
104
104
|
while True:
|
|
105
105
|
# reach is what will be added to the attractor at each step
|
|
@@ -180,7 +180,7 @@ class ParityGame:
|
|
|
180
180
|
|
|
181
181
|
# Solve subgame once subgame - B has been solved
|
|
182
182
|
# (notice that the subgame variable is not really the
|
|
183
|
-
# subgame, which is
|
|
183
|
+
# subgame, which is no longer needed, but B)
|
|
184
184
|
elif phase == 2:
|
|
185
185
|
B = subgame
|
|
186
186
|
result[1-player].update(B)
|
|
@@ -382,7 +382,7 @@ class MuMaudeGame(ParityGame):
|
|
|
382
382
|
node = self.add_state(player, 0)
|
|
383
383
|
|
|
384
384
|
elif head == '~_':
|
|
385
|
-
# Formulae
|
|
385
|
+
# Formulae are assumed to be in negative normal form
|
|
386
386
|
player = 0 if self.check_aprop(state, self.formula_nodes[fnode.children[0]].extra) else 1
|
|
387
387
|
node = self.add_state(player, 0)
|
|
388
388
|
|
|
@@ -440,7 +440,7 @@ class MuMaudeGame(ParityGame):
|
|
|
440
440
|
self.add_edge(parent, node)
|
|
441
441
|
|
|
442
442
|
def solve_mucalc(self):
|
|
443
|
-
"""
|
|
443
|
+
"""Solve the μ-calculus game"""
|
|
444
444
|
|
|
445
445
|
self.build()
|
|
446
446
|
w0, w1 = self.solve()
|
umaudemc/backend/ltsmin.py
CHANGED
|
@@ -330,7 +330,7 @@ class LTSmin:
|
|
|
330
330
|
aprops = set()
|
|
331
331
|
collect_aprops(formula, aprops)
|
|
332
332
|
|
|
333
|
-
# Create
|
|
333
|
+
# Create an instance of LTSmin and run it
|
|
334
334
|
runner = self.new_runner()
|
|
335
335
|
runner.set_module(module_str, metamodule_str, labels, opaque)
|
|
336
336
|
runner.add_formula(formula, logic, aprops)
|
umaudemc/backend/nusmv.py
CHANGED
|
@@ -315,7 +315,7 @@ class NuSMVGrapher:
|
|
|
315
315
|
print(' esac;', file=self.outfile)
|
|
316
316
|
|
|
317
317
|
def explore(self, graph, stateNr, bound=-1):
|
|
318
|
-
"""Explore the graph up to
|
|
318
|
+
"""Explore the graph up to an optional given depth, adding the nodes to the visited set"""
|
|
319
319
|
# Depth-first search with a stack
|
|
320
320
|
pending = [(stateNr, bound)]
|
|
321
321
|
self.visited.add(stateNr)
|
umaudemc/backend/prism.py
CHANGED
|
@@ -136,7 +136,7 @@ def make_prism_query(form, aprops, deterministic, raw_form=None, cost=False, rew
|
|
|
136
136
|
else:
|
|
137
137
|
full_formula = f'{query}=? [ {prism_formula} ]'
|
|
138
138
|
|
|
139
|
-
# Otherwise, if the model is
|
|
139
|
+
# Otherwise, if the model is an MDP, we calculate the minimum
|
|
140
140
|
# and maximum probabilities for the formula
|
|
141
141
|
else:
|
|
142
142
|
# Multiple formulae are admitted separated by semicolon
|
|
@@ -148,7 +148,7 @@ def make_prism_query(form, aprops, deterministic, raw_form=None, cost=False, rew
|
|
|
148
148
|
def collect_raw_aprops(form, aprops):
|
|
149
149
|
"""Collect atomic propositions from raw formula"""
|
|
150
150
|
|
|
151
|
-
# The start of the last string, whether
|
|
151
|
+
# The start of the last string, whether an escape character
|
|
152
152
|
# has been just seen, the algorithm state (out, string or braces),
|
|
153
153
|
# and the position where the current proposition starts
|
|
154
154
|
last, escaped, state, pos = 0, False, 'o', 0
|
|
@@ -208,7 +208,7 @@ class PRISMBasedBackend:
|
|
|
208
208
|
# Output the DTMC or MDP for the model
|
|
209
209
|
# Expand the graph and calculate the output degrees
|
|
210
210
|
grapher.graph(graph)
|
|
211
|
-
# Output the map of
|
|
211
|
+
# Output the map of a user-specified reward
|
|
212
212
|
if reward is not None:
|
|
213
213
|
grapher.make_reward(graph, 'user', reward)
|
|
214
214
|
|
umaudemc/backend/spin.py
CHANGED
|
@@ -295,7 +295,7 @@ class SpinGrapher:
|
|
|
295
295
|
print(' od\n}', file=self.outfile)
|
|
296
296
|
|
|
297
297
|
def explore(self, graph, stateNr, bound=-1):
|
|
298
|
-
"""Explore the graph up to
|
|
298
|
+
"""Explore the graph up to an optional given depth, adding the nodes to the visited set"""
|
|
299
299
|
# Depth-first search with a stack
|
|
300
300
|
pending = [(stateNr, bound)]
|
|
301
301
|
self.visited.add(stateNr)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Admissibility checking subcommand
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from ..common import parse_initial_data, usermsgs
|
|
8
|
+
# Meter las herramientas en backends y usar la misma estrategia que en otros contextos
|
|
9
|
+
|
|
10
|
+
def acheck(args):
|
|
11
|
+
"""Admissibility check subcommand"""
|
|
12
|
+
|
|
13
|
+
# Parse the module data
|
|
14
|
+
data = parse_initial_data(args, only_module=True)
|
|
15
|
+
|
|
16
|
+
if data is None:
|
|
17
|
+
return 1
|
|
18
|
+
|
|
19
|
+
print(data.module)
|
|
20
|
+
|
|
21
|
+
return 0
|
umaudemc/command/graph.py
CHANGED
|
@@ -11,7 +11,7 @@ from shutil import which
|
|
|
11
11
|
from ..common import maude, usermsgs, default_model_settings, parse_initial_data, split_comma
|
|
12
12
|
from ..formatter import get_formatters
|
|
13
13
|
from ..grapher import DOTGrapher, PDOTGrapher, TikZGrapher
|
|
14
|
-
from ..wrappers import
|
|
14
|
+
from ..wrappers import wrap_graph
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ProcessStream:
|
|
@@ -96,6 +96,18 @@ def graph(args):
|
|
|
96
96
|
args.merge_states,
|
|
97
97
|
args.strategy)
|
|
98
98
|
|
|
99
|
+
# Check the Kleene iteration flag
|
|
100
|
+
kleene_graph = False
|
|
101
|
+
|
|
102
|
+
if args.kleene_iteration:
|
|
103
|
+
if not with_strategy:
|
|
104
|
+
usermsgs.print_warning('The --kleene-iteration flag should only be used with a strategy. Ignoring.')
|
|
105
|
+
elif args.passign:
|
|
106
|
+
usermsgs.print_warning('The --kleene-iteration flag cannot be used with probabilities. Ignoring.')
|
|
107
|
+
else:
|
|
108
|
+
kleene_graph = True
|
|
109
|
+
|
|
110
|
+
|
|
99
111
|
# Select the appropriate rewriting graph
|
|
100
112
|
# (probabilistic, strategy-controlled, or standard)
|
|
101
113
|
if args.passign or oformat in ('prism', 'jani'):
|
|
@@ -106,20 +118,25 @@ def graph(args):
|
|
|
106
118
|
purge_fails=args.purge_fails,
|
|
107
119
|
merge_states=args.merge_states)
|
|
108
120
|
|
|
121
|
+
elif kleene_graph:
|
|
122
|
+
from ..kleene import get_kleene_graph
|
|
123
|
+
rwgraph = get_kleene_graph(initial_data)
|
|
124
|
+
rwgraph = wrap_graph(rwgraph, purge_fails, merge_states)
|
|
125
|
+
|
|
109
126
|
elif not with_strategy:
|
|
110
127
|
rwgraph = maude.RewriteGraph(initial_data.term)
|
|
111
128
|
|
|
112
129
|
else:
|
|
113
130
|
rwgraph = maude.StrategyRewriteGraph(initial_data.term, initial_data.strategy,
|
|
114
131
|
initial_data.opaque, initial_data.full_matchrew)
|
|
115
|
-
rwgraph =
|
|
132
|
+
rwgraph = wrap_graph(rwgraph, purge_fails, merge_states)
|
|
116
133
|
|
|
117
134
|
# If something has failed when creating the graph
|
|
118
135
|
if rwgraph is None:
|
|
119
136
|
return 1
|
|
120
137
|
|
|
121
138
|
# It is possible to generate models of the NuSMV and PRISM model checkers instead of
|
|
122
|
-
# DOT graphs. They
|
|
139
|
+
# DOT graphs. They can be annotated with atomic propositions that are checked in the states.
|
|
123
140
|
if args.aprops is not None:
|
|
124
141
|
aprops = [initial_data.module.parseTerm(prop) for prop in split_comma(args.aprops)]
|
|
125
142
|
|
|
@@ -129,8 +146,19 @@ def graph(args):
|
|
|
129
146
|
else:
|
|
130
147
|
aprops = []
|
|
131
148
|
|
|
149
|
+
# State and edge labels
|
|
132
150
|
slabel, elabel = get_formatters(args.slabel, args.elabel, with_strategy, only_labels=True)
|
|
133
151
|
|
|
152
|
+
if kleene_graph:
|
|
153
|
+
# Extend the label with the iteration flags
|
|
154
|
+
original_elabel = elabel
|
|
155
|
+
|
|
156
|
+
def kleene_elabel(stmt):
|
|
157
|
+
iterations_txt = ''.join(f'{" +" if enter else " -"}{iid}' for iid, enter in stmt.iterations)
|
|
158
|
+
return f'{original_elabel(stmt)}{iterations_txt}'
|
|
159
|
+
|
|
160
|
+
elabel = kleene_elabel
|
|
161
|
+
|
|
134
162
|
# Whether the graph should be seen as a CTMC and probabilities should not be normalized
|
|
135
163
|
is_ctmc = args.passign and args.passign.startswith('ctmc-')
|
|
136
164
|
|
umaudemc/command/scheck.py
CHANGED
|
@@ -61,7 +61,7 @@ def plot_results(program, qdata):
|
|
|
61
61
|
rs.append(query.h)
|
|
62
62
|
|
|
63
63
|
else:
|
|
64
|
-
# Parametric queries with less
|
|
64
|
+
# Parametric queries with less than two points are
|
|
65
65
|
# ignored (line plots do not make sense for them)
|
|
66
66
|
if len(xs) > 1:
|
|
67
67
|
results.append((index, xs, ys, rs))
|
umaudemc/command/test.py
CHANGED
|
@@ -64,9 +64,9 @@ def load_cases(filename):
|
|
|
64
64
|
|
|
65
65
|
extension = os.path.splitext(filename)[1]
|
|
66
66
|
|
|
67
|
-
# The YAML package is only loaded
|
|
68
|
-
#
|
|
69
|
-
if extension in
|
|
67
|
+
# The YAML package is only loaded when needed
|
|
68
|
+
# (pyaml is an optional dependency)
|
|
69
|
+
if extension in ('.yaml', '.yml'):
|
|
70
70
|
try:
|
|
71
71
|
import yaml
|
|
72
72
|
from yaml.loader import SafeLoader
|
|
@@ -79,7 +79,7 @@ def load_cases(filename):
|
|
|
79
79
|
|
|
80
80
|
# The YAML loader is replaced so that entities have its line number
|
|
81
81
|
# associated to print more useful messages. This is not possible with
|
|
82
|
-
# the standard JSON library
|
|
82
|
+
# the standard JSON library.
|
|
83
83
|
|
|
84
84
|
class SafeLineLoader(SafeLoader):
|
|
85
85
|
def construct_mapping(self, node, deep=False):
|
|
@@ -89,16 +89,34 @@ def load_cases(filename):
|
|
|
89
89
|
return mapping
|
|
90
90
|
|
|
91
91
|
try:
|
|
92
|
-
with open(filename
|
|
92
|
+
with open(filename) as caspec:
|
|
93
93
|
return yaml.load(caspec, Loader=SafeLineLoader)
|
|
94
94
|
|
|
95
95
|
except yaml.error.YAMLError as ype:
|
|
96
96
|
usermsgs.print_error(f'Error while parsing test file: {ype}.')
|
|
97
97
|
|
|
98
|
+
# TOML format
|
|
99
|
+
if extension == '.toml':
|
|
100
|
+
try:
|
|
101
|
+
import tomllib
|
|
102
|
+
|
|
103
|
+
except ImportError:
|
|
104
|
+
usermsgs.print_error(
|
|
105
|
+
'Cannot load cases from TOML file, '
|
|
106
|
+
'which is only available since Python 3.10.')
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
with open(filename) as caspec:
|
|
111
|
+
return tomllib.load(caspec)
|
|
112
|
+
|
|
113
|
+
except tomllib.TOMLDecodeError as tde:
|
|
114
|
+
usermsgs.print_error(f'Error while parsing test file: {tde}.')
|
|
115
|
+
|
|
98
116
|
# JSON format
|
|
99
117
|
else:
|
|
100
118
|
try:
|
|
101
|
-
with open(filename
|
|
119
|
+
with open(filename) as caspec:
|
|
102
120
|
return json.load(caspec)
|
|
103
121
|
|
|
104
122
|
except json.JSONDecodeError as jde:
|
|
@@ -321,7 +339,7 @@ class ParameterSet:
|
|
|
321
339
|
# Fields admitted by the test specification format
|
|
322
340
|
# (some others keys are admitted but treated apart)
|
|
323
341
|
#
|
|
324
|
-
# They
|
|
342
|
+
# They consist of a name, a type, the function that need to be called for
|
|
325
343
|
# parsing them, and the arguments that must be reparsed because of it.
|
|
326
344
|
|
|
327
345
|
TEST_FIELDS = {
|
|
@@ -524,7 +542,7 @@ def read_cases(filename, source, parser, skip=0):
|
|
|
524
542
|
if test.initial is None or test.formula is None:
|
|
525
543
|
usermsgs.print_error((f'Missing initial state or formula for a test case in file {test.rel_filename}'
|
|
526
544
|
f'(line {test.line_number}).') if len(test_stack) > 0 else
|
|
527
|
-
|
|
545
|
+
f'Expected cases for file {test.rel_filename}.')
|
|
528
546
|
return None, None
|
|
529
547
|
|
|
530
548
|
# Whether the model has changed
|
|
@@ -573,7 +591,7 @@ def _run_backend(name, backend, case, timeout, args):
|
|
|
573
591
|
timeout=timeout)
|
|
574
592
|
|
|
575
593
|
|
|
576
|
-
def run_tests(suite, backends, args, only_file=None, only_logic=None, resume=None, **
|
|
594
|
+
def run_tests(suite, backends, args, only_file=None, only_logic=None, resume=None, **_):
|
|
577
595
|
"""Run the tests in the suite with the first backend available"""
|
|
578
596
|
|
|
579
597
|
for source, cases in suite:
|
|
@@ -964,7 +982,7 @@ def _memory_case(memusage, psutil, case, name, backend, args, log, maudebin=None
|
|
|
964
982
|
total,
|
|
965
983
|
peak,
|
|
966
984
|
stack
|
|
967
|
-
|
|
985
|
+
))
|
|
968
986
|
|
|
969
987
|
|
|
970
988
|
def memory_tests(suite, backends, args, only_file=None, only_logic=None,
|
umaudemc/common.py
CHANGED
|
@@ -14,30 +14,6 @@ from . import usermsgs
|
|
|
14
14
|
# Warn about old versions of the maude package installed
|
|
15
15
|
#
|
|
16
16
|
|
|
17
|
-
if hasattr(maude, 'StateTransitionGraph'):
|
|
18
|
-
usermsgs.print_warning('Version 0.3 of the maude package contains bugs related to model checking.\n'
|
|
19
|
-
'Please update.')
|
|
20
|
-
|
|
21
|
-
# Anyhow, allow using it at their own risk, for which some adaptations are needed
|
|
22
|
-
maude.RewriteGraph = maude.StateTransitionGraph
|
|
23
|
-
maude.StrategyRewriteGraph = maude.StrategyTransitionGraph
|
|
24
|
-
|
|
25
|
-
maude.Symbol.__call__ = lambda self, *args: self.makeTerm(args)
|
|
26
|
-
|
|
27
|
-
if not hasattr(maude, 'Hook'):
|
|
28
|
-
usermsgs.print_warning('Version 0.5 of the maude package adds some useful features for this program.\n'
|
|
29
|
-
'Please update.')
|
|
30
|
-
|
|
31
|
-
maude.RewriteGraph.getNrRewrites = lambda: 0
|
|
32
|
-
maude.StrategyRewriteGraph.getNrRewrites = lambda: 0
|
|
33
|
-
maude.ModelCheckResult.nrBuchiStates = 0
|
|
34
|
-
maude.downModule = lambda term: term.symbol().getModule().downModule(term)
|
|
35
|
-
maude.Sort.__le__ = lambda self, other: self.leq(other)
|
|
36
|
-
maude.Term.__eq__ = lambda self, other: self.equal(other)
|
|
37
|
-
|
|
38
|
-
if not hasattr(maude.StrategyRewriteGraph, 'getNrRealStates'):
|
|
39
|
-
maude.StrategyRewriteGraph.getNrRealStates = maude.StrategyRewriteGraph.getNrStates
|
|
40
|
-
|
|
41
17
|
if not hasattr(maude.Term, 'getVarName'):
|
|
42
18
|
usermsgs.print_warning('Version 1.0 of the maude package adds some useful features for this program.\n'
|
|
43
19
|
'Please update.')
|
umaudemc/counterprint.py
CHANGED
|
@@ -78,17 +78,21 @@ def print_counterexample(graph, counter, printer_triple):
|
|
|
78
78
|
next_index = lead_in[i+1] if i+1 < len(lead_in) else cycle[0]
|
|
79
79
|
|
|
80
80
|
if graph.strategyControlled:
|
|
81
|
+
trans = graph.getTransition(index, next_index)
|
|
82
|
+
|
|
81
83
|
printer.next_step_strat(
|
|
82
84
|
sformat(graph, index),
|
|
83
85
|
graph.getStateStrategy(index),
|
|
84
|
-
eformat(
|
|
86
|
+
eformat(trans),
|
|
85
87
|
sformat(graph, next_index),
|
|
86
88
|
first_index=index,
|
|
87
89
|
second_index=next_index)
|
|
88
90
|
else:
|
|
91
|
+
rule = graph.getRule(index, next_index)
|
|
92
|
+
|
|
89
93
|
printer.next_step(
|
|
90
94
|
sformat(graph, index),
|
|
91
|
-
eformat(
|
|
95
|
+
eformat(rule),
|
|
92
96
|
sformat(graph, next_index),
|
|
93
97
|
first_index=index,
|
|
94
98
|
second_index=next_index)
|
|
@@ -103,17 +107,21 @@ def print_counterexample(graph, counter, printer_triple):
|
|
|
103
107
|
next_index = cycle[i+1] if i+1 < len(cycle) else cycle[0]
|
|
104
108
|
|
|
105
109
|
if graph.strategyControlled:
|
|
110
|
+
trans = graph.getTransition(index, next_index)
|
|
111
|
+
|
|
106
112
|
printer.next_step_strat(
|
|
107
113
|
sformat(graph, index),
|
|
108
114
|
graph.getStateStrategy(index),
|
|
109
|
-
eformat(
|
|
115
|
+
eformat(trans),
|
|
110
116
|
sformat(graph, next_index),
|
|
111
117
|
first_index=index,
|
|
112
118
|
second_index=next_index)
|
|
113
119
|
else:
|
|
120
|
+
rule = graph.getRule(index, next_index)
|
|
121
|
+
|
|
114
122
|
printer.next_step(
|
|
115
123
|
sformat(graph, index),
|
|
116
|
-
eformat(
|
|
124
|
+
eformat(rule),
|
|
117
125
|
sformat(graph, next_index),
|
|
118
126
|
first_index=index,
|
|
119
127
|
second_index=next_index)
|
umaudemc/data/smcgraph.js
CHANGED
umaudemc/data/smcview.js
CHANGED
|
@@ -38,13 +38,11 @@ function browseDir(dir)
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
var question =
|
|
42
|
-
|
|
43
|
-
question.append('question', 'ls')
|
|
44
|
-
question.append('url', dir)
|
|
41
|
+
var question = {question: 'ls', url: dir}
|
|
45
42
|
|
|
46
43
|
request.open('post', 'ask')
|
|
47
|
-
request.
|
|
44
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
45
|
+
request.send(JSON.stringify(question))
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
function openFile(file)
|
|
@@ -57,6 +55,23 @@ function openFile(file)
|
|
|
57
55
|
loadSourceModules(file)
|
|
58
56
|
}
|
|
59
57
|
|
|
58
|
+
function loadSourceNative()
|
|
59
|
+
{
|
|
60
|
+
const request = new XMLHttpRequest()
|
|
61
|
+
|
|
62
|
+
request.onreadystatechange = function()
|
|
63
|
+
{
|
|
64
|
+
if (this.readyState == XMLHttpRequest.DONE && this.status == 200)
|
|
65
|
+
{
|
|
66
|
+
console.log(this.responseText)
|
|
67
|
+
openFile(this.responseText)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
request.open('get', 'umaudemc://open/')
|
|
72
|
+
request.send()
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
function incompletePassign()
|
|
61
76
|
{
|
|
62
77
|
switch (document.getElementById('pmethod').value) {
|
|
@@ -193,11 +208,10 @@ function loadSourceModules(file)
|
|
|
193
208
|
// Discard modules from previous files
|
|
194
209
|
smodule.options.length = 0
|
|
195
210
|
|
|
196
|
-
var question =
|
|
197
|
-
question.append('question', 'sourceinfo')
|
|
198
|
-
question.append('url', file)
|
|
211
|
+
var question = {question: 'sourceinfo', url: file}
|
|
199
212
|
request.open('post', 'ask')
|
|
200
|
-
request.
|
|
213
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
214
|
+
request.send(JSON.stringify(question))
|
|
201
215
|
}
|
|
202
216
|
|
|
203
217
|
function addPropToFormula(prop)
|
|
@@ -318,11 +332,11 @@ function loadModule()
|
|
|
318
332
|
|
|
319
333
|
description.innerText = 'Please select a Maude file and a Maude module defining the system and properties specification.'
|
|
320
334
|
|
|
321
|
-
var question =
|
|
322
|
-
|
|
323
|
-
question.append('mod', currentModule)
|
|
335
|
+
var question = {question: 'modinfo', mod: currentModule}
|
|
336
|
+
|
|
324
337
|
request.open('post', 'ask')
|
|
325
|
-
request.
|
|
338
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
339
|
+
request.send(JSON.stringify(question))
|
|
326
340
|
}
|
|
327
341
|
|
|
328
342
|
function modelcheck()
|
|
@@ -356,14 +370,14 @@ function modelcheck()
|
|
|
356
370
|
}
|
|
357
371
|
}
|
|
358
372
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
373
|
+
const question = {
|
|
374
|
+
question: 'modelcheck',
|
|
375
|
+
mod: document.getElementById('module').value,
|
|
376
|
+
initial: document.getElementById('initial').value,
|
|
377
|
+
formula: document.getElementById('formula').value,
|
|
378
|
+
strategy: document.getElementById('strategy').value,
|
|
379
|
+
opaques: document.getElementById('opaques').value
|
|
380
|
+
}
|
|
367
381
|
|
|
368
382
|
// Quantitative model checking stuff
|
|
369
383
|
if (document.getElementById('command').value == 'qt')
|
|
@@ -375,7 +389,8 @@ function modelcheck()
|
|
|
375
389
|
}
|
|
376
390
|
|
|
377
391
|
request.open('post', 'ask')
|
|
378
|
-
request.
|
|
392
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
393
|
+
request.send(JSON.stringify(question))
|
|
379
394
|
}
|
|
380
395
|
|
|
381
396
|
function escapeHTMLChars(text) {
|
|
@@ -460,17 +475,15 @@ function waitModelChecker(mcref) {
|
|
|
460
475
|
// Disable input until model checking has finished
|
|
461
476
|
disableInput(true)
|
|
462
477
|
|
|
463
|
-
|
|
478
|
+
const question = {question: 'wait', mcref: mcref}
|
|
464
479
|
|
|
465
|
-
question.append('question', 'wait')
|
|
466
|
-
question.append('mcref', mcref)
|
|
467
480
|
request.open('post', 'ask')
|
|
468
|
-
request.
|
|
481
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
482
|
+
request.send(JSON.stringify(question))
|
|
469
483
|
}
|
|
470
484
|
|
|
471
485
|
function cancelChecking() {
|
|
472
486
|
const request = new XMLHttpRequest()
|
|
473
|
-
const question = new FormData()
|
|
474
487
|
|
|
475
488
|
request.onreadystatechange = function()
|
|
476
489
|
{
|
|
@@ -486,9 +499,9 @@ function cancelChecking() {
|
|
|
486
499
|
}
|
|
487
500
|
}
|
|
488
501
|
|
|
489
|
-
question.append('question', 'cancel')
|
|
490
502
|
request.open('post', 'ask')
|
|
491
|
-
request.
|
|
503
|
+
request.setRequestHeader('Content-Type', 'application/json')
|
|
504
|
+
request.send('{"question": "cancel"}')
|
|
492
505
|
}
|
|
493
506
|
|
|
494
507
|
function closeResultDialog()
|