156
|
1 |
(* The I/O automata of Lynch and Tuttle. *)
|
|
2 |
|
|
3 |
IOA = Asig +
|
|
4 |
|
|
5 |
types
|
|
6 |
'a seq = "nat => 'a"
|
|
7 |
'a oseq = "nat => 'a option"
|
|
8 |
('a,'b)execution = "'a oseq * 'b seq"
|
|
9 |
('a,'s)transition = "('s * 'a * 's)"
|
|
10 |
('a,'s)ioa = "'a signature * 's set * ('a,'s)transition set"
|
|
11 |
|
|
12 |
consts
|
|
13 |
|
|
14 |
(* IO automata *)
|
|
15 |
state_trans::"['action signature, ('action,'state)transition set] => bool"
|
|
16 |
asig_of ::"('action,'state)ioa => 'action signature"
|
|
17 |
starts_of ::"('action,'state)ioa => 'state set"
|
|
18 |
trans_of ::"('action,'state)ioa => ('action,'state)transition set"
|
|
19 |
IOA ::"('action,'state)ioa => bool"
|
|
20 |
|
|
21 |
(* Executions, schedules, and behaviours *)
|
|
22 |
|
|
23 |
is_execution_fragment,
|
|
24 |
has_execution ::"[('action,'state)ioa, ('action,'state)execution] => bool"
|
|
25 |
executions :: "('action,'state)ioa => ('action,'state)execution set"
|
|
26 |
mk_behaviour :: "[('action,'state)ioa, 'action oseq] => 'action oseq"
|
|
27 |
reachable :: "[('action,'state)ioa, 'state] => bool"
|
|
28 |
invariant :: "[('action,'state)ioa, 'state=>bool] => bool"
|
|
29 |
has_behaviour :: "[('action,'state)ioa, 'action oseq] => bool"
|
|
30 |
behaviours :: "('action,'state)ioa => 'action oseq set"
|
|
31 |
|
|
32 |
(* Composition of action signatures and automata *)
|
|
33 |
compatible_asigs ::"('a => 'action signature) => bool"
|
|
34 |
asig_composition ::"('a => 'action signature) => 'action signature"
|
|
35 |
compatible_ioas ::"('a => ('action,'state)ioa) => bool"
|
|
36 |
ioa_composition ::"('a => ('action, 'state)ioa) =>('action,'a => 'state)ioa"
|
|
37 |
|
|
38 |
(* binary composition of action signatures and automata *)
|
|
39 |
compat_asigs ::"['action signature, 'action signature] => bool"
|
|
40 |
asig_comp ::"['action signature, 'action signature] => 'action signature"
|
|
41 |
compat_ioas ::"[('action,'state)ioa, ('action,'state)ioa] => bool"
|
|
42 |
"||" ::"[('a,'s)ioa, ('a,'t)ioa] => ('a,'s*'t)ioa" (infixr 10)
|
|
43 |
|
|
44 |
(* Filtering and hiding *)
|
|
45 |
filter_oseq :: "('a => bool) => 'a oseq => 'a oseq"
|
|
46 |
|
|
47 |
restrict_asig :: "['a signature, 'a set] => 'a signature"
|
|
48 |
restrict :: "[('a,'s)ioa, 'a set] => ('a,'s)ioa"
|
|
49 |
|
|
50 |
(* Notions of correctness *)
|
|
51 |
ioa_implements :: "[('action,'state1)ioa, ('action,'state2)ioa] => bool"
|
|
52 |
|
|
53 |
|
|
54 |
rules
|
|
55 |
|
|
56 |
state_trans_def
|
|
57 |
"state_trans(asig,R) == \
|
|
58 |
\ (!triple. triple:R --> fst(snd(triple)):actions(asig)) & \
|
|
59 |
\ (!a. (a:inputs(asig)) --> (!s1. ? s2. <s1,a,s2>:R))"
|
|
60 |
|
|
61 |
|
|
62 |
ioa_projections_def
|
|
63 |
"asig_of = fst & starts_of = (fst o snd) & trans_of = (snd o snd)"
|
|
64 |
|
|
65 |
|
|
66 |
ioa_def
|
|
67 |
"IOA(ioa) == (is_asig(asig_of(ioa)) & \
|
|
68 |
\ (~ starts_of(ioa) = {}) & \
|
|
69 |
\ state_trans(asig_of(ioa),trans_of(ioa)))"
|
|
70 |
|
|
71 |
|
|
72 |
(* An execution fragment is modelled with a pair of sequences:
|
|
73 |
* the first is the action options, the second the state sequence.
|
|
74 |
* Finite executions have None actions from some point on.
|
|
75 |
*******)
|
|
76 |
is_execution_fragment_def
|
|
77 |
"is_execution_fragment(A,ex) == \
|
|
78 |
\ let act = fst(ex); state = snd(ex) \
|
|
79 |
\ in !n a. (act(n)=None --> state(Suc(n)) = state(n)) & \
|
|
80 |
\ (act(n)=Some(a) --> <state(n),a,state(Suc(n))>:trans_of(A))"
|
|
81 |
|
|
82 |
|
|
83 |
executions_def
|
|
84 |
"executions(ioa) == {e. snd(e,0):starts_of(ioa) & \
|
|
85 |
\ is_execution_fragment(ioa,e)}"
|
|
86 |
|
|
87 |
|
|
88 |
(* Is a state reachable. Using an inductive definition, this could be defined
|
|
89 |
* by the following 2 rules
|
|
90 |
*
|
|
91 |
* x:starts_of(ioa)
|
|
92 |
* ----------------
|
|
93 |
* reachable(ioa,x)
|
|
94 |
*
|
|
95 |
* reachable(ioa,s) & ? <s,a,s'>:trans_of(ioa)
|
|
96 |
* -------------------------------------------
|
|
97 |
* reachable(ioa,s')
|
|
98 |
*
|
|
99 |
* A direkt definition follows.
|
|
100 |
*******************************)
|
|
101 |
reachable_def
|
|
102 |
"reachable(ioa,s) == (? ex:executions(ioa). ? n. snd(ex,n) = s)"
|
|
103 |
|
|
104 |
|
|
105 |
invariant_def "invariant(A,P) == (!s. reachable(A,s) --> P(s))"
|
|
106 |
|
|
107 |
|
|
108 |
(* Restrict the trace to those members of the set s *)
|
|
109 |
filter_oseq_def
|
|
110 |
"filter_oseq(p,s) == \
|
|
111 |
\ (%i.case s(i) \
|
|
112 |
\ of None => None \
|
|
113 |
\ | Some(x) => if(p(x),Some(x),None))"
|
|
114 |
|
|
115 |
|
|
116 |
mk_behaviour_def
|
|
117 |
"mk_behaviour(ioa) == filter_oseq(%a.a:externals(asig_of(ioa)))"
|
|
118 |
|
|
119 |
|
|
120 |
(* Does an ioa have an execution with the given behaviour *)
|
|
121 |
has_behaviour_def
|
|
122 |
"has_behaviour(ioa,b) == \
|
|
123 |
\ (? ex:executions(ioa). b = mk_behaviour(ioa,fst(ex)))"
|
|
124 |
|
|
125 |
|
|
126 |
(* All the behaviours of an ioa *)
|
|
127 |
behaviours_def
|
|
128 |
"behaviours(ioa) == {b. has_behaviour(ioa,b)}"
|
|
129 |
|
|
130 |
|
|
131 |
compat_asigs_def
|
|
132 |
"compat_asigs (a1,a2) == \
|
|
133 |
\ (((outputs(a1) Int outputs(a2)) = {}) & \
|
|
134 |
\ ((internals(a1) Int actions(a2)) = {}) & \
|
|
135 |
\ ((internals(a2) Int actions(a1)) = {}))"
|
|
136 |
|
|
137 |
|
|
138 |
compat_ioas_def
|
|
139 |
"compat_ioas(ioa1,ioa2) == compat_asigs (asig_of(ioa1)) (asig_of(ioa2))"
|
|
140 |
|
|
141 |
|
|
142 |
asig_comp_def
|
|
143 |
"asig_comp (a1,a2) == \
|
|
144 |
\ (<(inputs(a1) Un inputs(a2)) - (outputs(a1) Un outputs(a2)), \
|
|
145 |
\ (outputs(a1) Un outputs(a2)), \
|
|
146 |
\ (internals(a1) Un internals(a2))>)"
|
|
147 |
|
|
148 |
|
|
149 |
par_def
|
|
150 |
"(ioa1 || ioa2) == \
|
|
151 |
\ <asig_comp(asig_of(ioa1),asig_of(ioa2)), \
|
|
152 |
\ {pr. fst(pr):starts_of(ioa1) & snd(pr):starts_of(ioa2)}, \
|
|
153 |
\ {tr. let s = fst(tr); a = fst(snd(tr)); t = snd(snd(tr)) \
|
|
154 |
\ in (a:actions(asig_of(ioa1)) | a:actions(asig_of(ioa2))) & \
|
|
155 |
\ if(a:actions(asig_of(ioa1)), \
|
|
156 |
\ <fst(s),a,fst(t)>:trans_of(ioa1), \
|
|
157 |
\ fst(t) = fst(s)) \
|
|
158 |
\ & \
|
|
159 |
\ if(a:actions(asig_of(ioa2)), \
|
|
160 |
\ <snd(s),a,snd(t)>:trans_of(ioa2), \
|
|
161 |
\ snd(t) = snd(s))}>"
|
|
162 |
|
|
163 |
|
|
164 |
restrict_asig_def
|
|
165 |
"restrict_asig(asig,actns) == \
|
|
166 |
\ <inputs(asig) Int actns, outputs(asig) Int actns, \
|
|
167 |
\ internals(asig) Un (externals(asig) - actns)>"
|
|
168 |
|
|
169 |
|
|
170 |
restrict_def
|
|
171 |
"restrict(ioa,actns) == \
|
|
172 |
\ <restrict_asig(asig_of(ioa),actns), starts_of(ioa), trans_of(ioa)>"
|
|
173 |
|
|
174 |
|
|
175 |
ioa_implements_def
|
|
176 |
"ioa_implements(ioa1,ioa2) == \
|
|
177 |
\ (externals(asig_of(ioa1)) = externals(asig_of(ioa2)) & \
|
|
178 |
\ behaviours(ioa1) <= behaviours(ioa2))"
|
|
179 |
|
|
180 |
end
|