umaudemc 0.12.2__py3-none-any.whl → 0.13.1__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/kleene.py ADDED
@@ -0,0 +1,156 @@
1
+ #
2
+ # Strategy execution machine and graph for the Kleene star semantics
3
+ #
4
+
5
+ from .common import maude
6
+ from .pyslang import GraphRunner, GraphExecutionState
7
+
8
+
9
+ class KleeneExecutionState(GraphExecutionState):
10
+ """Execution state for generating a graph"""
11
+
12
+ def __init__(self, term, pc, stack, conditional=False, graph_node=None, extra=None, iterations=None):
13
+ super().__init__(term, pc, stack, conditional, graph_node,
14
+ (extra, set() if iterations is None else iterations))
15
+
16
+ def copy(self, term=None, pc=None, stack=None, conditional=False, graph_node=None, extra=None):
17
+ """Clone state with possibly some changes"""
18
+
19
+ return KleeneExecutionState(
20
+ self.term if term is None else term,
21
+ self.pc + 1 if pc is None else pc,
22
+ self.stack if stack is None else stack,
23
+ conditional,
24
+ self.graph_node if graph_node is None else graph_node,
25
+ self.extra[0] if extra is None else extra,
26
+ self.extra[1],
27
+ )
28
+
29
+ def add_kleene(self, args):
30
+ """Add iteration labels"""
31
+ self.extra = (self.extra[0], self.extra[1] | {args})
32
+
33
+ def reset_extra(self):
34
+ """Reset the extra attribute"""
35
+ self.extra = (self.extra[0], set())
36
+
37
+
38
+ class KleeneRunner(GraphRunner):
39
+ """Runner that extract a Streett automaton with the Kleene star semantics"""
40
+
41
+ def __init__(self, program, term):
42
+ super().__init__(program, term, state_class=KleeneExecutionState)
43
+ self.iter_contexts = {}
44
+
45
+ def kleene(self, args, stack):
46
+ """Keep track of iterations"""
47
+ context_id = self.iter_contexts.setdefault(self.current_state.stack, len(self.iter_contexts))
48
+ self.current_state.add_kleene(((args[0], context_id), args[1]))
49
+ super().kleene(args, stack)
50
+
51
+
52
+ class StrategyKleeneGraph:
53
+ """Strategy-controlled graph with iteration tracking"""
54
+
55
+ # This is mostly copied from StrategyMarkovGraph
56
+ # (merging some of the code should be considered)
57
+
58
+ # This graph is always strategy-controlled
59
+ strategyControlled = True
60
+
61
+ class Transition:
62
+ """Transition of the StrategyKleeneGraph"""
63
+
64
+ def __init__(self, pair=None):
65
+ self.rule, self.iterations = pair
66
+
67
+ def getRule(self):
68
+ return self.rule
69
+
70
+ def getType(self):
71
+ return (maude.StrategyRewriteGraph.SOLUTION if self.rule is None
72
+ else maude.StrategyRewriteGraph.RULE_APPLICATION)
73
+
74
+ def __init__(self, root, nrew):
75
+ self.state_list = [root]
76
+ self.state_map = {root: 0}
77
+ self.nr_rewrites = nrew
78
+
79
+ def getStateTerm(self, state):
80
+ return self.state_list[state].term
81
+
82
+ def getStateStrategy(self, state):
83
+ return ''
84
+
85
+ def getNrRewrites(self):
86
+ return self.nr_rewrites
87
+
88
+ def getNrRealStates(self):
89
+ return len(self.state_list)
90
+
91
+ def getNrStates(self):
92
+ return len(self.state_list)
93
+
94
+ def states(self):
95
+ """Iterator through the states (numbers) of the graph"""
96
+ return range(len(self.state_list))
97
+
98
+ def getTransition(self, origin, dest):
99
+ """Get one of the transitions from one state to another"""
100
+
101
+ actions = self.state_list[origin].actions[self.state_list[dest]]
102
+ return self.Transition(actions[0]) if actions else self.Transition()
103
+
104
+ def getNextStates(self, stateNr):
105
+ """Iterator through the successors of a state"""
106
+
107
+ for next_state in self.state_list[stateNr].children:
108
+ yield self.state_map[next_state]
109
+
110
+ def getTransitions(self, stateNr):
111
+ """Iterator through the transitions of the graph"""
112
+
113
+ state = self.state_list[stateNr]
114
+ for next_state in state.children:
115
+ actions = state.actions[next_state]
116
+ for action in (actions if actions else (None,)):
117
+ yield self.state_map[next_state], self.Transition(action)
118
+
119
+ def expand(self):
120
+ """Expand the underlying graph"""
121
+
122
+ for k, state in enumerate(self.state_list):
123
+ for child in state.children:
124
+ if child not in self.state_map:
125
+ self.state_map[child] = len(self.state_list)
126
+ self.state_list.append(child)
127
+
128
+
129
+ def get_kleene_graph(data):
130
+ """Get the Kleene-aware graph for a strategy (with InputData)"""
131
+
132
+ return get_kleene_graph_mts(data.module, data.term, data.strategy)
133
+
134
+
135
+ def get_kleene_graph_mts(module, term, strategy):
136
+ """Get the Kleene-aware graph for a strategy"""
137
+
138
+ from . import pyslang
139
+
140
+ ml = maude.getModule('META-LEVEL')
141
+
142
+ # Initialize the strategy compiler and optimizer
143
+ sc = pyslang.StratCompiler(module, ml, use_notify=True, use_kleene=True, ignore_one=True)
144
+
145
+ # Compile the strategy
146
+ p = sc.compile(ml.upStrategy(strategy))
147
+
148
+ # Reduce the term
149
+ nrew_initial = term.reduce()
150
+
151
+ root, nrew = KleeneRunner(p, term).run()
152
+ graph = StrategyKleeneGraph(root, nrew + nrew_initial)
153
+
154
+ graph.expand()
155
+
156
+ return graph
umaudemc/opsem.py CHANGED
@@ -125,7 +125,7 @@ class OpSemInstance:
125
125
  return self.stack_state(term_meta, strategy_meta)
126
126
 
127
127
  def make_graph(self, initial, strategy, opaques=()):
128
- """Get the strategy for the strategy-controlled rewriting"""
128
+ """Get the graph for the strategy-controlled rewriting"""
129
129
 
130
130
  # Build the initial term
131
131
  t = self.make_initial_term(initial, strategy)
umaudemc/probabilistic.py CHANGED
@@ -604,6 +604,9 @@ class AssignedGraph:
604
604
  def getRule(self, *args):
605
605
  return self.graph.getRule(*args)
606
606
 
607
+ def getTransition(self, *args):
608
+ return self.graph.getTransition(*args)
609
+
607
610
  def states(self):
608
611
  """Iterator through the states (numbers) of the graph"""
609
612
  return self.visited
@@ -756,17 +759,17 @@ class StrategyMarkovGraph:
756
759
  return (maude.StrategyRewriteGraph.SOLUTION if self.rule is None
757
760
  else maude.StrategyRewriteGraph.RULE_APPLICATION)
758
761
 
759
- def __init__(self, root):
762
+ def __init__(self, root, nrew):
760
763
  self.state_list = [root]
761
764
  self.state_map = {root: 0}
762
765
  self.nondeterminism = False
766
+ self.nr_rewrites = nrew
763
767
 
764
768
  def getStateTerm(self, state):
765
769
  return self.state_list[state].term
766
770
 
767
771
  def getNrRewrites(self):
768
- # The number of rewrites is not counted in this implementation
769
- return 0
772
+ return self.nr_rewrites
770
773
 
771
774
  def getNrRealStates(self):
772
775
  return len(self.state_list)
@@ -816,8 +819,8 @@ class StrategyMarkovGraph:
816
819
  class StrategyMetadataGraph(StrategyMarkovGraph):
817
820
  """Strategic graph with probabilities given by non-ground metadata"""
818
821
 
819
- def __init__(self, root, mdp=False):
820
- super().__init__(root)
822
+ def __init__(self, root, nrew, mdp=False):
823
+ super().__init__(root, nrew)
821
824
  self.nondeterminism = mdp
822
825
 
823
826
  def getTransition(self, origin, dest):
@@ -887,11 +890,11 @@ def get_probabilistic_strategy_graph(module, strategy, term, stmt_map=None, mdp=
887
890
 
888
891
  # Execute the strategy with the corresponding runner
889
892
  if stmt_map is None:
890
- root = pyslang.MarkovRunner(p, term).run()
891
- graph = StrategyMarkovGraph(root)
893
+ root, nrew = pyslang.MarkovRunner(p, term).run()
894
+ graph = StrategyMarkovGraph(root, nrew)
892
895
  else:
893
- root = pyslang.MetadataRunner(p, term, stmt_map).run()
894
- graph = StrategyMetadataGraph(root, mdp)
896
+ root, nrew = pyslang.MetadataRunner(p, term, stmt_map).run()
897
+ graph = StrategyMetadataGraph(root, nrew, mdp)
895
898
 
896
899
  graph.expand()
897
900