umaudemc 0.13.0__py3-none-any.whl → 0.14.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 CHANGED
@@ -1 +1 @@
1
- __version__ = '0.12.2'
1
+ __version__ = '0.14.0'
@@ -80,7 +80,7 @@ class StormBackend:
80
80
  builder.add_next_value(row=st, column=st, value=1.0)
81
81
 
82
82
  def _build_mdp(self, builder, graph):
83
- """Build an MDP from the probabilsitic rewrite graph"""
83
+ """Build an MDP from the probabilistic rewrite graph"""
84
84
 
85
85
  last_visited, row_index, num_states = -1, 0, len(graph)
86
86
 
@@ -127,7 +127,6 @@ class StormBackend:
127
127
  self._build_mdp(builder, graph)
128
128
 
129
129
  transition_matrix = builder.build()
130
- #input(transition_matrix)
131
130
 
132
131
  # State labeling with atomic propositions
133
132
  state_labeling = stormpy.storage.StateLabeling(num_states)
@@ -233,7 +232,7 @@ class StormBackend:
233
232
  def state_analysis(self, *args, **kwargs):
234
233
  """Steady and transient state analysis"""
235
234
 
236
- # StormPy does not allow calculting state probabilities, as far as we know, so
235
+ # StormPy does not allow calculating state probabilities, as far as we know, so
237
236
  # we delegate on the command-line interface to Storm
238
237
  from ._storm import StormBackend as StormCmdLineBackend
239
238
 
@@ -479,22 +479,22 @@ class BuiltinBackend:
479
479
  return [modop, self.ctl2mucalc(rest[0], index=index)]
480
480
  elif head == '_U_':
481
481
  return ['mu_._', ['Var', f'Z{index}'], ['_\\/_',
482
- self.ctl2mucalc(rest[1], index=index + 1),
483
- ['_/\\_', self.ctl2mucalc(rest[0], index=index + 1),
484
- [modop, ['Var', f'Z{index}']]]]]
482
+ self.ctl2mucalc(rest[1], index=index + 1),
483
+ ['_/\\_', self.ctl2mucalc(rest[0], index=index + 1),
484
+ [modop, ['Var', f'Z{index}']]]]]
485
485
  elif head == '_R_':
486
486
  return ['nu_._', ['Var', f'Z{index}'], ['_/\\_',
487
- self.ctl2mucalc(rest[1], index=index + 1),
488
- ['_\\/_', self.ctl2mucalc(rest[0], index=index + 1),
489
- [modop, ['Var', f'Z{index}']]]]]
487
+ self.ctl2mucalc(rest[1], index=index + 1),
488
+ ['_\\/_', self.ctl2mucalc(rest[0], index=index + 1),
489
+ [modop, ['Var', f'Z{index}']]]]]
490
490
  elif head == '`[`]_':
491
491
  return ['nu_._', ['Var', f'Z{index}'], ['_/\\_',
492
- self.ctl2mucalc(rest[0], index=index + 1),
493
- [modop, ['Var', f'Z{index}']]]]
492
+ self.ctl2mucalc(rest[0], index=index + 1),
493
+ [modop, ['Var', f'Z{index}']]]]
494
494
  elif head == '<>_':
495
495
  return ['mu_._', ['Var', f'Z{index}'], ['_\\/_',
496
- self.ctl2mucalc(rest[0], index=index + 1),
497
- [modop, ['Var', f'Z{index}']]]]
496
+ self.ctl2mucalc(rest[0], index=index + 1),
497
+ [modop, ['Var', f'Z{index}']]]]
498
498
  else:
499
499
  return [head] + [self.ctl2mucalc(arg, index=index) for arg in rest]
500
500
 
@@ -552,7 +552,7 @@ class LTSminRunner:
552
552
  maude_lib_ltsmin = os.getenv('MAUDE_LIB_LTSMIN')
553
553
  new_maude_lib = os.getenv('MAUDE_LIB', '') if maude_lib_ltsmin is None else maude_lib_ltsmin
554
554
  new_maude_lib = ('' if new_maude_lib == '' else new_maude_lib + os.pathsep) \
555
- + os.path.dirname(filename)
555
+ + os.path.dirname(filename)
556
556
 
557
557
  if raw:
558
558
  os.execve(self.ltsmin.pins2lts[variant], [self.ltsmin.pins2lts[variant]] + args,
umaudemc/command/check.py CHANGED
@@ -8,7 +8,7 @@ import sys
8
8
  import tempfile
9
9
 
10
10
  from ..common import parse_initial_data, usermsgs
11
- from ..backends import kleene_backends, get_backends, backend_for, format_statistics,\
11
+ from ..backends import kleene_backends, get_backends, backend_for, format_statistics, \
12
12
  advance_counterexample, advance_kleene
13
13
  from ..counterprint import SimplePrinter, JSONPrinter, HTMLPrinter, DOTPrinter, print_counterexample
14
14
  from ..formulae import Parser, collect_aprops, add_path_premise, formula_list2str
umaudemc/command/graph.py CHANGED
@@ -71,7 +71,7 @@ def deduce_format(args):
71
71
  usermsgs.print_warning('PDF output is only supported with DOT. Changing to DOT.')
72
72
  return 'dot'
73
73
 
74
- # Probabilitic information is not considered in some cases
74
+ # Probabilistic information is not considered in some cases
75
75
  if args.passign and oformat not in ('dot', 'prism', 'jani', 'default'):
76
76
  usermsgs.print_warning('Probabilistic graphs are only supported with PRISM, JANI and DOT output. '
77
77
  'Ignoring probabilities.')
@@ -107,7 +107,6 @@ def graph(args):
107
107
  else:
108
108
  kleene_graph = True
109
109
 
110
-
111
110
  # Select the appropriate rewriting graph
112
111
  # (probabilistic, strategy-controlled, or standard)
113
112
  if args.passign or oformat in ('prism', 'jani'):
@@ -50,6 +50,7 @@ def _print_fraction(value):
50
50
 
51
51
  return f'{num}/{den}' if num > 0 and den != 1 else num
52
52
 
53
+
53
54
  def _select_backend(known_backends, backend_list):
54
55
  """Get the first available backend according to the user preferences"""
55
56
 
@@ -78,7 +79,6 @@ def _select_backend(known_backends, backend_list):
78
79
  elif first_known is None:
79
80
  first_known = name
80
81
 
81
-
82
82
  if first_available is None:
83
83
  if first_known is None:
84
84
  usermsgs.print_error('The backend list does not contain any valid option.')
umaudemc/command/test.py CHANGED
@@ -280,7 +280,7 @@ def _depends_on_vars(node, variables):
280
280
 
281
281
 
282
282
  class ParameterSet:
283
- """Assignement to parameters to be replaced on test attributes"""
283
+ """Assignment to parameters to be replaced on test attributes"""
284
284
 
285
285
  def __init__(self, dic, is_subs=None):
286
286
  # Dictionary with the parameter assignments
umaudemc/common.py CHANGED
@@ -18,7 +18,8 @@ if not hasattr(maude.Term, 'getVarName'):
18
18
  usermsgs.print_warning('Version 1.0 of the maude package adds some useful features for this program.\n'
19
19
  'Please update.')
20
20
 
21
- maude.Term.getVarName = lambda self: str(self).split(':')[0] if self.symbol() == self.symbol().getModule().parseTerm(f'$$$:{self.getSort()}').symbol() else None
21
+ maude.Term.getVarName = lambda self: str(self).split(':')[0] if self.symbol() == \
22
+ self.symbol().getModule().parseTerm(f'$$$:{self.getSort()}').symbol() else None
22
23
  maude.Term.isVariable = lambda self: self.getVarName() is None
23
24
 
24
25
 
umaudemc/data/select.htm CHANGED
@@ -85,7 +85,7 @@
85
85
  <option value="metadata">Weighted by metadata</option>
86
86
  <option value="strategy">Probabilistic strategy</option>
87
87
  </select>
88
- <input type="checkbox" id="mdp" style="margin-left: 1.5ex; display: none;"></input>
88
+ <input type="checkbox" id="mdp" style="margin-left: 1.5ex; display: none;"/>
89
89
  <label for="mdp" style="display: none;">MDP</label>
90
90
  <label for="parg" style="margin-left: 1.5ex; display: none;">Weight term:</label>
91
91
  <input type="text" id="parg" style="flex-grow: 1; display: none;" onchange="buttonToggle()"
umaudemc/formatter.py CHANGED
@@ -19,7 +19,7 @@ def apply_state_format(graph, index, sformat, terms, use_term=False, use_strat=F
19
19
  :type sformat: str
20
20
  :param terms: Term patterns to appear in the format string.
21
21
  :type terms: list of string
22
- :param use_term: Whether the term is actually used (only for effiency).
22
+ :param use_term: Whether the term is actually used (only for efficiency).
23
23
  :type use_term: bool
24
24
  :param use_strat: Whether the strategy is actually used (only for effiency).
25
25
  :type use_strat: bool
umaudemc/opsem.py CHANGED
@@ -65,7 +65,7 @@ class OpSemInstance:
65
65
 
66
66
  @classmethod
67
67
  def get_instantiation(cls, module, metamodule=None, semantics_module=None, preds_module=None):
68
- """Get the Maude code to instantiate the sematnics for the given problem"""
68
+ """Get the Maude code to instantiate the semantics for the given problem"""
69
69
 
70
70
  # Use the default semantics and predicates module if not specified
71
71
  if semantics_module is None:
umaudemc/probabilistic.py CHANGED
@@ -714,7 +714,7 @@ class GeneralizedMetadataGraph:
714
714
  edges = []
715
715
 
716
716
  for child, subs, ctx, rl in term.apply(None):
717
- # Term.apply do not reduce the terms itself
717
+ # Term.apply does not reduce the terms itself
718
718
  self.rewrite_count += 1 + child.reduce()
719
719
  index = self.term_map.get(child)
720
720
 
umaudemc/pyslang.py CHANGED
@@ -30,7 +30,7 @@ class Instruction:
30
30
  RWCSTART = 11 # list of (pattern, condition, starting pattern)
31
31
  RWCNEXT = 12 # list of (end pattern, condition, starting pattern/right-hand side)
32
32
  NOTIFY = 13 # list of lists of variables of the nested pending matchrew subterms
33
- SAMPLE = 14 # (variable, distribution callable, its arguments)
33
+ SAMPLE = 14 # (variable, distribution sampler, distribution generator, its arguments)
34
34
  WMATCHREW = 15 # like MATCHREW + (weight)
35
35
  ONE = 16 # no arguments
36
36
  CHECKPOINT = 17 # no arguments
@@ -130,12 +130,30 @@ def merge_substitutions(sb1, sb2):
130
130
  return maude.Substitution({**dict(sb1), **dict(sb2)})
131
131
 
132
132
 
133
- def bernoulli_distrib(p):
134
- """Bernoulli distribution"""
133
+ def bernoulli_sampler(p):
134
+ """Bernoulli distribution sampler"""
135
135
 
136
136
  return 1.0 if random.random() < p else 0.0
137
137
 
138
138
 
139
+ def bernoulli_distribution(p):
140
+ """Explicit Bernoulli distribution"""
141
+
142
+ return (p, 1.0), (1 - p, 0.0)
143
+
144
+
145
+ def uniform_sampler(start, end):
146
+ """Integer uniform distribution sampler"""
147
+
148
+ return random.randint(start, end + 1)
149
+
150
+
151
+ def uniform_distribution(start, end):
152
+ """Explicit uniform distribution"""
153
+
154
+ return ((1, k) for k in range(start, end + 1))
155
+
156
+
139
157
  def find_cycles(initial, next_fn):
140
158
  """Find cycles in the graph and return the points where to cut them"""
141
159
 
@@ -290,6 +308,9 @@ class StratCompiler:
290
308
  self.mtc_symbol = ml.findSymbol('_:=_', (term_kind, term_kind), condition_kind)
291
309
  self.stc_symbol = ml.findSymbol('_:_', (term_kind, term_kind), condition_kind)
292
310
 
311
+ # Kind of natural numbers (if any)
312
+ self.nat_kind = self.get_special_kind('ACU_NumberOpSymbol')
313
+
293
314
  # Program counters of the generated strategy calls
294
315
  self.calls = []
295
316
 
@@ -311,6 +332,13 @@ class StratCompiler:
311
332
 
312
333
  return list(term.arguments())
313
334
 
335
+ def get_special_kind(self, hook):
336
+ """Get a special kind by the hook name of one of its symbols"""
337
+
338
+ for s in self.m.getSymbols():
339
+ if (id_hooks := s.getIdHooks()) and id_hooks[0][0] == hook:
340
+ return s.getRangeSort().kind()
341
+
314
342
  def substitution2dict(self, substitution):
315
343
  """Convert a metalevel substitution to a dictionary"""
316
344
 
@@ -670,15 +698,26 @@ class StratCompiler:
670
698
  name = str(name)[1:]
671
699
  args = tuple(map(self.m.downTerm, self.get_list(args, self.empty_term_list, self.term_list_symbol)))
672
700
 
673
- name = {
674
- 'bernoulli': bernoulli_distrib,
675
- 'uniform': random.uniform,
701
+ # Whether the distribution is discrete
702
+ discrete = name == 'bernoulli' or (name == 'uniform' and self.nat_kind is not None
703
+ and all(arg.getSort().kind() == self.nat_kind for arg in args))
704
+
705
+ # Sampler to obtain one value from the distribution
706
+ sampler = {
707
+ 'bernoulli': bernoulli_sampler,
708
+ 'uniform': uniform_sampler if discrete else random.uniform,
676
709
  'exp': random.expovariate,
677
710
  'norm': random.normalvariate,
678
711
  'gamma': random.gammavariate,
679
712
  }[name]
680
713
 
681
- p.append(Instruction.SAMPLE, (self.m.downTerm(variable), name, args))
714
+ # Full distribution generator (for graph generation in discrete distributions)
715
+ generator = None
716
+
717
+ if discrete:
718
+ generator = bernoulli_distribution if name == 'bernoulli' else uniform_distribution
719
+
720
+ p.append(Instruction.SAMPLE, (self.m.downTerm(variable), sampler, generator, args))
682
721
  self.generate(strat, p, tail)
683
722
  p.append(Instruction.POP)
684
723
 
@@ -1478,6 +1517,9 @@ class StratRunner:
1478
1517
  elif stack.pc:
1479
1518
  self.current_state.pc = stack.pc
1480
1519
 
1520
+ else:
1521
+ self.current_state.pc += 1
1522
+
1481
1523
  # Pop the stack node
1482
1524
  if stack.parent:
1483
1525
  self.current_state.stack = self.current_state.stack.parent
@@ -1835,10 +1877,10 @@ class StratRunner:
1835
1877
 
1836
1878
  self.next_pending()
1837
1879
 
1838
- def sample(self, args, stack):
1839
- """Sample a probability distribution into a variable"""
1880
+ def sample_get_params(self, args, stack):
1881
+ """Extract distribution parameters from a sample call"""
1840
1882
 
1841
- variable, dist, dargs = args
1883
+ _, _, generator, dargs = args
1842
1884
 
1843
1885
  # Arguments of the distribution instantiated in the variable context
1844
1886
  dargs = [(stack.venv.instantiate(arg) if stack.venv else arg) for arg in dargs]
@@ -1847,9 +1889,20 @@ class StratRunner:
1847
1889
  for arg in dargs:
1848
1890
  self.nr_rewrites += arg.reduce()
1849
1891
 
1850
- dargs = [float(arg) for arg in dargs]
1892
+ # Argument type to convert arguments
1893
+ atype = float if generator is not uniform_distribution else int
1894
+
1895
+ return [atype(arg) for arg in dargs]
1896
+
1897
+ def sample(self, args, stack):
1898
+ """Sample a probability distribution into a variable"""
1899
+
1900
+ variable, sampler, _, dargs = args
1901
+
1902
+ dargs = self.sample_get_params(args, stack)
1851
1903
 
1852
- new_variable = {variable: variable.symbol().getModule().parseTerm(str(dist(*dargs)))}
1904
+ module = variable.symbol().getModule()
1905
+ new_variable = {variable: module.parseTerm(str(sampler(*dargs)))}
1853
1906
 
1854
1907
  self.current_state.pc += 1
1855
1908
  self.current_state.stack = StackNode(parent=self.current_state.stack,
@@ -1963,7 +2016,7 @@ class GraphState:
1963
2016
 
1964
2017
 
1965
2018
  class BadProbStrategy(Exception):
1966
- """Bad probabilitistic strategy that cannot engender MDPs or DTMCs"""
2019
+ """Bad probabilistic strategy that cannot engender MDPs or DTMCs"""
1967
2020
 
1968
2021
  def __init__(self):
1969
2022
  super().__init__('Strategies are not allowed to make nondeterministic choices '
@@ -2001,7 +2054,7 @@ class GraphRunner(StratRunner):
2001
2054
 
2002
2055
  # Solution states, indexed by term (we introduce them as children
2003
2056
  # of graph states where both a solution of the strategy and a
2004
- # different sucessor can be reached)
2057
+ # different successor can be reached)
2005
2058
  self.solution_states = {}
2006
2059
 
2007
2060
  def get_solution_state(self, term):
@@ -2081,9 +2134,12 @@ class GraphRunner(StratRunner):
2081
2134
  """Return from a strategy call or similar construct"""
2082
2135
 
2083
2136
  # Return from a strategy call
2084
- if stack.pc:
2137
+ if stack.pc is not None:
2085
2138
  self.current_state.pc = stack.pc
2086
2139
 
2140
+ else:
2141
+ self.current_state.pc += 1
2142
+
2087
2143
  # Actually pop the stack node
2088
2144
  if stack.parent:
2089
2145
  self.current_state.stack = self.current_state.stack.parent
@@ -2189,6 +2245,27 @@ class GraphRunner(StratRunner):
2189
2245
 
2190
2246
  self.next_pending()
2191
2247
 
2248
+ def sample(self, args, stack):
2249
+ variable, sampler, generator, dargs = args
2250
+
2251
+ # Only special behavior for discrete distributions
2252
+ if not generator:
2253
+ return super().sample(args, stack)
2254
+
2255
+ # Arguments of the distribution instantiated in the variable context
2256
+ dargs = self.sample_get_params(args, stack)
2257
+
2258
+ # Generate a pending state for each possible outcome
2259
+ module = variable.symbol().getModule()
2260
+
2261
+ for _, value in generator(*dargs):
2262
+ self.pending.append(self.current_state.copy(stack=StackNode(
2263
+ parent=self.current_state.stack,
2264
+ venv=merge_substitutions(stack.venv, {variable: module.parseTerm(str(value))})))
2265
+ )
2266
+
2267
+ self.next_pending()
2268
+
2192
2269
  def run(self):
2193
2270
  """Run the strategy to generate the graph"""
2194
2271
 
@@ -2298,20 +2375,8 @@ class MarkovRunner(GraphRunner):
2298
2375
 
2299
2376
  graph_state.child_choices = tuple(new_choices)
2300
2377
 
2301
- def choice(self, args, stack):
2302
- """A choice node"""
2303
-
2304
- weights, targets = zip(*args)
2305
- weights = list(self.compute_weights(weights, stack.venv))
2306
-
2307
- # Remove options with null weight
2308
- targets = [target for k, target in enumerate(targets) if weights[k] != 0.0]
2309
- weights = [w for w in weights if w != 0.0]
2310
-
2311
- # If there is only a positive weight, we can proceed with it
2312
- if len(weights) == 1:
2313
- self.current_state.pc = targets[0]
2314
- return
2378
+ def spawn_choice(self, weights, new_xss):
2379
+ """Spawn tasks for a choice"""
2315
2380
 
2316
2381
  # Otherwise, if there is at least one
2317
2382
  if weights:
@@ -2323,8 +2388,7 @@ class MarkovRunner(GraphRunner):
2323
2388
  # These graph states cannot be pushed to the DFS stack (because we
2324
2389
  # are not exploring them yet), they should be pushed when the
2325
2390
  # execution state new_xs is executed, so we add them to push_state
2326
- for k, target in enumerate(targets):
2327
- new_xs = self.current_state.copy(pc=target)
2391
+ for k, new_xs in enumerate(new_xss):
2328
2392
  self.pending.append(new_xs)
2329
2393
  self.push_state[new_xs] = new_states[k]
2330
2394
 
@@ -2333,6 +2397,26 @@ class MarkovRunner(GraphRunner):
2333
2397
 
2334
2398
  self.next_pending()
2335
2399
 
2400
+ def choice(self, args, stack):
2401
+ """A choice node"""
2402
+
2403
+ weights, targets = zip(*args)
2404
+ weights = list(self.compute_weights(weights, stack.venv))
2405
+
2406
+ # Remove options with null weight
2407
+ targets = [target for k, target in enumerate(targets) if weights[k] != 0.0]
2408
+ weights = [w for w in weights if w != 0.0]
2409
+
2410
+ # If there is only a positive weight, we can proceed with it
2411
+ if len(weights) == 1:
2412
+ self.current_state.pc = targets[0]
2413
+ return
2414
+
2415
+ # New execution states
2416
+ new_xss = (self.current_state.copy(pc=target) for target in targets)
2417
+
2418
+ self.spawn_choice(weights, new_xss)
2419
+
2336
2420
  def wmatchrew(self, args, stack):
2337
2421
  """A matchrew with weight node"""
2338
2422
 
@@ -2376,24 +2460,34 @@ class MarkovRunner(GraphRunner):
2376
2460
  self.current_state = new_xss[0]
2377
2461
  return
2378
2462
 
2379
- # Otherwise, if there is at least one
2380
- if weights:
2381
- graph_state = self.dfs_stack[-1]
2463
+ self.spawn_choice(weights, new_xss)
2382
2464
 
2383
- # Create a new graph state (without term) for each branch of the matchrew
2384
- new_states = [self.GraphState(None) for _ in range(len(weights))]
2465
+ def sample(self, args, stack):
2466
+ variable, sampler, generator, dargs = args
2385
2467
 
2386
- # These graph states cannot be pushed to the DFS stack (because we
2387
- # are not exploring them yet), they should be pushed when the
2388
- # execution state new_xss[k] is executed, so we add them to push_state
2389
- for k in range(len(targets)):
2390
- self.pending.append(new_xss[k])
2391
- self.push_state[new_xss[k]] = new_states[k]
2468
+ # Only a special behavior for discrete distributions
2469
+ if not generator:
2470
+ return super().sample(args, stack)
2392
2471
 
2393
- # Add the resolved choice to the graph state
2394
- graph_state.child_choices.add(tuple(zip(weights, new_states)))
2472
+ # Arguments of the distribution instantiated in the variable context
2473
+ dargs = self.sample_get_params(args, stack)
2395
2474
 
2396
- self.next_pending()
2475
+ # Generate the distribution of options
2476
+ module = variable.symbol().getModule()
2477
+ weights, new_xss = [], []
2478
+
2479
+ for weight, value in generator(*dargs):
2480
+ weights.append(weight)
2481
+ new_xss.append(self.current_state.copy(stack=StackNode(
2482
+ parent=self.current_state.stack,
2483
+ venv=merge_substitutions(stack.venv, {variable: module.parseTerm(str(value))})
2484
+ )))
2485
+
2486
+ # If there is only a positive weight, we can proceed with it
2487
+ if len(weights) == 1:
2488
+ self.current_state = new_xss[0]
2489
+
2490
+ self.spawn_choice(weights, new_xss)
2397
2491
 
2398
2492
  def notify(self, args, stack):
2399
2493
  """Record a transition in the graph"""
@@ -2594,6 +2688,9 @@ class RandomRunner(StratRunner):
2594
2688
  if stack.pc:
2595
2689
  self.current_state.pc = stack.pc
2596
2690
 
2691
+ else:
2692
+ self.current_state.pc += 1
2693
+
2597
2694
  # Pop the stack node
2598
2695
  if stack.parent:
2599
2696
  self.current_state.stack = self.current_state.stack.parent
umaudemc/quatex.py CHANGED
@@ -458,8 +458,8 @@ class QuaTExParser:
458
458
  self.ok = False
459
459
 
460
460
  slot = self.fslots.setdefault(call_name, len(self.fslots))
461
- current = ast.Tuple([ast.Constant(inside_next), ast.Constant(slot), *args],
462
- ast.Load(), custom_loc=(call_line, call_column))
461
+ current = ast.Tuple([ast.Constant(inside_next), ast.Constant(slot), *args], ast.Load())
462
+ current.custom_loc = (call_line, call_column)
463
463
  self.calls.append((call_name, call_line, call_column, len(args)))
464
464
  inside_next = False
465
465
  call_name = None
umaudemc/resources.py CHANGED
@@ -3,45 +3,31 @@
3
3
  #
4
4
  # These are included in the package tree and they should be loaded
5
5
  # even if the package is distributed as a compressed archive. This is
6
- # possible with importlib.resources in 3.7 and its backport
7
- # importlib_resources in previous versions.
6
+ # possible with importlib.resources.
8
7
  #
9
8
 
10
- import sys
11
9
  import importlib.resources as pkg_resources
12
10
 
13
11
  from . import data # Import the data directory as a package
14
12
 
15
- # To avoid deprecation warnings in Python 3.11 and above
16
- if sys.version_info >= (3, 9):
17
-
18
- def get_resource_path(name):
19
- """Get a temporary filename for a given named resource"""
20
- return pkg_resources.as_file(pkg_resources.files(data) / name)
13
+ # Root for static resources
14
+ _DATA_ROOT = pkg_resources.files(data)
21
15
 
22
- def get_resource_content(name):
23
- """Get the string content of a given named resource"""
24
- return (pkg_resources.files(data) / name).read_text()
25
16
 
26
- def get_resource_binary(name):
27
- """Get the string content of a given named resource"""
28
- return (pkg_resources.files(data) / name).read_bytes()
17
+ def get_resource_path(name):
18
+ """Get a temporary filename for a given named resource"""
19
+ return pkg_resources.as_file(_DATA_ROOT / name)
29
20
 
30
- # For compatibility with Python 3.8
31
- else:
32
- def get_resource_path(name):
33
- """Get a temporary filename for a given named resource"""
34
- return pkg_resources.path(data, name)
35
21
 
22
+ def get_resource_content(name):
23
+ """Get the string content of a given named resource"""
24
+ return (_DATA_ROOT / name).read_text()
36
25
 
37
- def get_resource_content(name):
38
- """Get the string content of a given named resource"""
39
- return pkg_resources.read_text(data, name)
40
26
 
27
+ def get_resource_binary(name):
28
+ """Get the string content of a given named resource"""
29
+ return (_DATA_ROOT / name).read_bytes()
41
30
 
42
- def get_resource_binary(name):
43
- """Get the string content of a given named resource"""
44
- return pkg_resources.read_binary(data, name)
45
31
 
46
32
  def get_templog():
47
33
  """Get a temporary filename for the templog Maude file"""
umaudemc/simulators.py CHANGED
@@ -79,8 +79,9 @@ class BaseSimulator:
79
79
  if not t:
80
80
  t, var = parse_hole_term(self.module, observation)
81
81
  self.obs_cache[observation] = (t, var)
82
- subs = maude.Substitution({var: self.state})
83
- t = subs.instantiate(t)
82
+ if var is not None:
83
+ subs = maude.Substitution({var: self.state})
84
+ t = subs.instantiate(t)
84
85
  t.reduce()
85
86
 
86
87
  return float(t == self.true) if t.getSort() == self.bool_sort else float(t)
umaudemc/statistical.py CHANGED
@@ -221,6 +221,7 @@ def thread_main(program, qdata, simulator, num_sims, block_size, seed, queue, ba
221
221
  def run_parallel(program, qdata, num_sims, max_sim, simulator, alpha, delta, block_size, jobs, verbose=False):
222
222
  """Run the simulation in multiple threads"""
223
223
  import multiprocessing as mp
224
+ mp.set_start_method('fork', force=True)
224
225
 
225
226
  # When the number of jobs is zero or negative, we take the CPU count
226
227
  if jobs <= 0:
@@ -232,7 +233,7 @@ def run_parallel(program, qdata, num_sims, max_sim, simulator, alpha, delta, blo
232
233
  # Process communication stuff
233
234
 
234
235
  # Random number seeds
235
- seeds = [random.randint(0, 1e6) for _ in range(jobs)]
236
+ seeds = [random.getrandbits(20) for _ in range(jobs)]
236
237
  # Queue for transferring the query evaluations
237
238
  queue = mp.Queue()
238
239
  barrier = mp.Barrier(jobs + 1)
@@ -328,7 +329,7 @@ def check(program, simulator, seed, alpha, delta, block, min_sim, max_sim, jobs,
328
329
  for idict in make_parameter_dicts(qinfo[2])]
329
330
 
330
331
  # Run the simulations
331
- if jobs == 1:
332
+ if jobs == 1 and num_sims != 1:
332
333
  return run_single(program, qdata, num_sims, max_sim, simulator, alpha,
333
334
  delta, block, verbose=verbose)
334
335
  else:
umaudemc/webui.py CHANGED
@@ -142,7 +142,7 @@ class WinPathHandler(PathHandler):
142
142
 
143
143
 
144
144
  class ConnectionInfo:
145
- """Persisent server information"""
145
+ """Persistent server information"""
146
146
 
147
147
  def __init__(self):
148
148
  self.path_handler = WinPathHandler() if sys.platform == 'win32' else PathHandler()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: umaudemc
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: Unified Maude model-checking utility
5
5
  Author-email: ningit <ningit@users.noreply.github.com>
6
6
  License: GPLv3
@@ -13,18 +13,18 @@ Classifier: Intended Audience :: Science/Research
13
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
14
  Classifier: Topic :: Scientific/Engineering
15
15
  Classifier: Operating System :: OS Independent
16
- Requires-Python: >=3.7
16
+ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: maude >=1.0
19
+ Requires-Dist: maude>=1.0
20
20
  Provides-Extra: ctlstar
21
- Requires-Dist: pyModelChecking >=1.3.3 ; extra == 'ctlstar'
21
+ Requires-Dist: pyModelChecking>=1.3.3; extra == "ctlstar"
22
+ Provides-Extra: yaml
23
+ Requires-Dist: pyaml; extra == "yaml"
22
24
  Provides-Extra: plot
23
- Requires-Dist: matplotlib ; extra == 'plot'
25
+ Requires-Dist: matplotlib; extra == "plot"
24
26
  Provides-Extra: smc
25
- Requires-Dist: scipy ; extra == 'smc'
26
- Provides-Extra: yaml
27
- Requires-Dist: pyaml ; extra == 'yaml'
27
+ Requires-Dist: scipy; extra == "smc"
28
28
 
29
29
  # Unified Maude model-checking tool
30
30
 
@@ -1,34 +1,34 @@
1
- umaudemc/__init__.py,sha256=KzYlv9mV5BAclb_b4mb6NprSS8L9Xd0qsNzjQFwnp30,23
1
+ umaudemc/__init__.py,sha256=4pkGIcN2HdoT4OEADiR3LUoE-VfT0mtYYKhwVWEwVMY,23
2
2
  umaudemc/__main__.py,sha256=PBIa2mStJwNIK5YnwoCefEB_a59VLkHE_Zp_1hnMyg4,14060
3
3
  umaudemc/api.py,sha256=I-o5foy8NUlO4JT4pX9L7kkuHQG_8_GMkWlOKt708E8,19733
4
4
  umaudemc/backends.py,sha256=mzJkALYwcKPInT0lBiRsCxJSewKvx5j_akQsqWN1Ezo,4590
5
- umaudemc/common.py,sha256=5jtR_HLZmTDrZFU2Isd3tJudZdMD-RbkiuHMUA3wPiE,4922
5
+ umaudemc/common.py,sha256=Z1RQNwNpwHApsckHM4Zj5A0ClTuVKKKC1Lkgf9yYmqI,4926
6
6
  umaudemc/counterprint.py,sha256=vVqM_UjGRk_xeftFxBGI5m6cQXV7mf8KvbQ_fvAvSQk,9226
7
- umaudemc/formatter.py,sha256=36l0nc9IIe4B0_eW_PPfDTIxJj0mHKZfddCUugrEyjM,6024
7
+ umaudemc/formatter.py,sha256=nbQlIsR5Xv18OEcpJdnTDGqO9xGL_amvBGFMU2OmheU,6026
8
8
  umaudemc/formulae.py,sha256=jZPPDhjgsb7cs5rWvitiQoO0fd8JIlK98at2SN-LzVE,12156
9
9
  umaudemc/grapher.py,sha256=K1chKNNlEzQvfOsiFmRPJmd9OpxRIrg6OyiMW6gqOCU,4348
10
10
  umaudemc/gtk.py,sha256=61p4_OSFDfNHFD4lLz3QTZ7yZBra3RINmgbcnB-mUis,4249
11
11
  umaudemc/jani.py,sha256=N5tE28jZC_OsI041nXOn02THlokpweATtEK-nx9pfWE,4130
12
12
  umaudemc/kleene.py,sha256=Yxo9O2rjJNpS6y4Qfb_SP71tDrryV0KKUfmBIKXypwg,4458
13
13
  umaudemc/mproc.py,sha256=9X5pTb3Z3XHcdOo8ynH7I5RZQpjzm9xr4IBbEtaglUE,11766
14
- umaudemc/opsem.py,sha256=p49k8Dto0zJ7jeI8Ih5Q9bB4lqMQaF39kxprlvCMN3U,9448
15
- umaudemc/probabilistic.py,sha256=f1ZtV84mAuaaGSmYCpun8gaUi5PFGCPD96BUgYvvBGk,29304
16
- umaudemc/pyslang.py,sha256=m501iqJb4fVlIimpOy_tO7woK5QLkTWYav0no7onoXM,85099
17
- umaudemc/quatex.py,sha256=HQoiC8N7WnloHPBgNlcpWUi0NcIyUXm3IK_glfHbu4A,21611
18
- umaudemc/resources.py,sha256=k1sekrTafAcOb7GQN-mx2BgCBEBPUi-IR_4EjNjRRmU,1530
19
- umaudemc/simulators.py,sha256=gjCWR-TiPeOv65viH-djAkazqaLV0olwfbU6Nak2rdE,13205
20
- umaudemc/statistical.py,sha256=Az7r4uuB1XrO4akBiYu2th7DSPGzDDAacu6W5wJym-Q,9015
14
+ umaudemc/opsem.py,sha256=Xfdi9QGy-vcpmQ9ni8lBDAlKNw-fCRzYr6wnPbv6m1s,9448
15
+ umaudemc/probabilistic.py,sha256=MNvFeEd84-OYedSnyksZB87UckPfwizVNJepCItgRy8,29306
16
+ umaudemc/pyslang.py,sha256=zOfVGtfnOWDGghtaYLfQHq61KvbzVFmAM_0-upNhrTk,87753
17
+ umaudemc/quatex.py,sha256=sSgGXhHmu_7XqBvcEv7EtGeecZ704OB3B8NFk8XXD00,21600
18
+ umaudemc/resources.py,sha256=qKqvgLYTJVtsQHQMXFObyCLTo6-fssQeu_mG7tvVyD0,932
19
+ umaudemc/simulators.py,sha256=84W30MWWe4QRxK24RGA0zuwXjPya4wH18PrhPKdOpyU,13229
20
+ umaudemc/statistical.py,sha256=-UzP3g4Sy5L_dq2UEimobwu1qR70uEQnqKigsPEvyzU,9074
21
21
  umaudemc/terminal.py,sha256=B4GWLyW4Sdymgoavj418y4TI4MnWqNu3JS4BBoSYeTc,1037
22
22
  umaudemc/usermsgs.py,sha256=d3RfyBGEBmcV_c2MeXWCtZIiiM2vFnaHsN3MHwMnyAs,583
23
- umaudemc/webui.py,sha256=7dWf5VVl5dGN9oBVTT8m6F4v_QqEbsKSH67q5FljuT8,11071
23
+ umaudemc/webui.py,sha256=XlDV87tOOdcclHp2_oerrvHwRmCZdqAR4PppqeZm47A,11072
24
24
  umaudemc/wrappers.py,sha256=uz9JV1zBVqzkuoByUd569fEcSxT_00aCJw-jcDtrFpE,9399
25
25
  umaudemc/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  umaudemc/backend/_pymc.py,sha256=asfN3uc0PbizVTiBt0Hs1n7jxzUN629Baj90z5X8Gjc,6679
27
27
  umaudemc/backend/_spot.py,sha256=rwnXJG98kLsjjobeYdFh5RqK07al0bGMzjz2gLnUPOQ,9166
28
28
  umaudemc/backend/_storm.py,sha256=yhHPNxLOekr9ZdzZv5Jzv1K6R5hIrYKQ4SES0rds_0A,4675
29
- umaudemc/backend/_stormpy.py,sha256=KPbRkVYZhwlL007GfbJJc2VBHbBz3_UKqUNM0FV7PyU,8280
30
- umaudemc/backend/bmcalc.py,sha256=fE6RxIETYu-ywzrwRvWJP5ZZbZXuUbO6TdV4bcJjA6E,17502
31
- umaudemc/backend/ltsmin.py,sha256=iZNzVQ74oiMOdIv1zNW8oeiLzGO88ENqLfhPQ20i4E0,21103
29
+ umaudemc/backend/_stormpy.py,sha256=gdFFHupp6o-8IEk-NxBaSWFz7zohJWxj27CUdrMNeXg,8253
30
+ umaudemc/backend/bmcalc.py,sha256=cgV11KmvqT-k1TpsdFHJp1bPrY0Wmlh1pG8XkVpO8G4,17874
31
+ umaudemc/backend/ltsmin.py,sha256=5r7o8KTKiQeSW6xSK7sV08rs9l0wb4IOPizJW3T_n1o,21104
32
32
  umaudemc/backend/nusmv.py,sha256=ebHWUYv6IcOedD2qsafqyvmEjLaxMmCMBy3tyAfrYUE,10913
33
33
  umaudemc/backend/prism.py,sha256=a78MEMXDRD-QRheQIDiAgVKDPyqkQ8iTAWmRE6lsKH4,15502
34
34
  umaudemc/backend/pymc.py,sha256=_NXTEpXsf0s5_WE3-1y63jx6iKj2KSjmn8hZZcWMltI,309
@@ -36,24 +36,23 @@ umaudemc/backend/spin.py,sha256=fe5w1YyVQ3LHGiP7jVex5yXC17CwTHlPvM4B3j7kvwk,9663
36
36
  umaudemc/backend/spot.py,sha256=P7vkxhY7Tx9J_rOmlua3bfiO8iMgNIuEi25ZNYZRLHk,283
37
37
  umaudemc/backend/storm.py,sha256=FlhJ0ZkJO84GjEUxuE2hQQJxJoeE_lElBB5NJL4NXTU,276
38
38
  umaudemc/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- umaudemc/command/acheck.py,sha256=lEywzcr-yEszvVcEaCELBqN3FJBNpr8C6Xoo8qGWxrU,385
40
- umaudemc/command/check.py,sha256=fzRUGAHNudZPYFk94ekwKplv9N7Fhsrmf5pOFsvPZwA,12030
41
- umaudemc/command/graph.py,sha256=74U-yY9NEm5oTeUjspkwy6Ve_eLBTwx8LgZDzUk2LQw,6112
42
- umaudemc/command/pcheck.py,sha256=RcgwQn8xBgt9eZC1sE3JzR97MB0SC6Q1AXuiKkkzJes,7274
39
+ umaudemc/command/check.py,sha256=PyaPDMw5OnPxSIZ10U4we0b5tTrjnYKAtAeQkJh2uLE,12031
40
+ umaudemc/command/graph.py,sha256=JqGzESC2sn-LBh2sqctrij03ItzwDO808s2qkNKUle0,6112
41
+ umaudemc/command/pcheck.py,sha256=eV4e4GcOHanP4hcIhMKd5Js22_ONac6kYj70FXun3mY,7274
43
42
  umaudemc/command/scheck.py,sha256=eRGE-2SsOf6etIfJQ9dJe4cSch8qAs7IuOR94i-E1_U,4653
44
- umaudemc/command/test.py,sha256=4Uw83V-gVbm21L0Zkv3mKOUpamiNM-qMxGVAYs-trdY,38734
43
+ umaudemc/command/test.py,sha256=kPmV1-hIJMMxZLErqYYP50z95uME_3sLLUMXQuUy9fs,38733
45
44
  umaudemc/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
45
  umaudemc/data/opsem.maude,sha256=geDP3_RMgtS1rRmYOybJDCXn_-dyHHxg0JxfYg1ftv0,27929
47
46
  umaudemc/data/problog.maude,sha256=qvP90peT3J9gWi7I0x86jfrEXsVxDP5lcrUnSkTMhcY,3091
48
47
  umaudemc/data/result.htm,sha256=IwllBM3p4F-QFvOYZZR6bZicL-FuuPLainU9DUPPyNA,1766
49
- umaudemc/data/select.htm,sha256=g0eXHHFxRpxJ9tqOfSgn_QmSQy0E-ET7MimBllGk6vk,4600
48
+ umaudemc/data/select.htm,sha256=CC9lkczPnLgqxeiSyn2Kv3oxLuuciPjtBzOHfnSv-SE,4593
50
49
  umaudemc/data/smcgraph.js,sha256=iCNQNmsuGdL_GLnqVhGDisediFtedxw3C24rxSiQwx8,6674
51
50
  umaudemc/data/smcview.css,sha256=ExFqrMkSeaf8VxFrJXflyCsRW3FTwbv78q0Hoo2UVrM,3833
52
51
  umaudemc/data/smcview.js,sha256=_fHum1DRU1mhco-9-c6KqTLgiC5u_cCUf61jIK7wcIQ,14509
53
52
  umaudemc/data/templog.maude,sha256=TZ-66hVWoG6gp7gJpS6FsQn7dpBTLrr76bKo-UfHGcA,9161
54
- umaudemc-0.13.0.dist-info/LICENSE,sha256=MrEGL32oSWfnAZ0Bq4BZNcqnq3Mhp87Q4w6-deXfFnA,17992
55
- umaudemc-0.13.0.dist-info/METADATA,sha256=TxKYoZevbw_qjRETGj5rzpnrAmdWs2DEQcUT_zhgQdY,1693
56
- umaudemc-0.13.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
57
- umaudemc-0.13.0.dist-info/entry_points.txt,sha256=8rYRlLkn4orZtAoujDSeol1t_UFBrK0bfjmLTNv9B44,52
58
- umaudemc-0.13.0.dist-info/top_level.txt,sha256=Yo_CF78HLGBSblk3890qLcx6XZ17zHCbGcT9iG8sfMw,9
59
- umaudemc-0.13.0.dist-info/RECORD,,
53
+ umaudemc-0.14.0.dist-info/LICENSE,sha256=MrEGL32oSWfnAZ0Bq4BZNcqnq3Mhp87Q4w6-deXfFnA,17992
54
+ umaudemc-0.14.0.dist-info/METADATA,sha256=nQh_n1_3pCq1rF3X1l0Ps5DIt9hlSqgd5tCAwrYW9sI,1687
55
+ umaudemc-0.14.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
56
+ umaudemc-0.14.0.dist-info/entry_points.txt,sha256=8rYRlLkn4orZtAoujDSeol1t_UFBrK0bfjmLTNv9B44,52
57
+ umaudemc-0.14.0.dist-info/top_level.txt,sha256=Yo_CF78HLGBSblk3890qLcx6XZ17zHCbGcT9iG8sfMw,9
58
+ umaudemc-0.14.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,21 +0,0 @@
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